Ray Mairlot - Freelance 3D Artist
  • Gallery
  • Blog
  • Store
  • Contact
  • About

Animation Nodes: An Experiment

24/11/2017

Comments

 
I recently made my first foray in learning probably one of the most advanced Blender add-ons that exists: Animation Nodes (AN onwards). And by 'learning' I mean I've done one project in it and don't know when I'll do another.

Here is my first, and possibly last, test:

My first little test in #AnimationNodes in #b3d: pic.twitter.com/QtNEKGNRPI

— Ray Mairlot (@RayMairlot) October 13, 2017

Now I have the rather unenvious task of trying to explain how I did it. Because I said I would and it seemed like a good idea at the time and now it's two thousand and ninety-three words later and I've come back up to the top of this post to write about how long it's taken and how I regret saying I would explain it.

However, despite the time it's taken to write this, this isn't a step-by-step tutorial and will probably take some investigation of your own to get a similar result. I merely nudge you towards the door, you must stumble your own way through it.

There are 3 main parts to re-creating the effect:

  1. Filling an object with other objects.
  2. Scaling the objects with AN.
  3. Creating the 'wave' effect with AN.

When I first started this mini-project I wasn't even intending to use AN, I was just trying to see if it were possible to fill an object with lots of other objects. It was only after looking at the sphere-filled torus that I wondered if I could animate it nicely.

My point is, at least in this version, the generating of the spheres to fill the torus was done beforehand. I would eventually like to try doing this step more procedurally as well, but for now this is a much more manual process.

Now, if you are ready to have some learning flung at you, proceed to the first part.


The Filling The Torus With Spheres Part


I'm not going to go into mega-detail for this part (or indeed any part), but the basic process is to fill a torus with a particle system of spheres and then use a rigid body system to allow the spheres to settle into non-intersecting positions:

  1. Fill an object with particles by using an 'Emitter' type particle system set to volume and a sphere as the Dupli Object (with particles set to start and end on frame 1).
  2. Convert the particle system to separate objects (Ctrl + A > Make duplicates real), make them all single users (U > Object & Data) and apply rotations and scales (Ctrl + A again).
  3. Set the new spheres to rigid bodies.
  4. Make the torus a passive rigid body set to Mesh and flip its normals so the rigid body system knows you your intention is for the rigid bodies to collide with the inside of the mesh.
  5. Turn off gravity (set gravity values to '0' in the Scene tab in the Properties Editor) and run the simulation.
  6. Discard any spheres that escaped the torus. They are dead to us now.
  7. On a frame where the spheres have settled, select all spheres and apply the Visual Transform (Ctrl + A > Visual Transform). This sets the spheres' positions to their positions as calculated by the rigid body simulation.
  8. Remove the rigid body settings from the spheres.

After doing this project I actually found someone had already done nearly the exact same steps (explained in far more detail) in their own YouTube tutorial here.


The First Animation Nodes Part


This is the part where the real 'fun' begins:

#AnimationNodes is great, but it does somtimes (at least at the beginning) feel like building your own brick wall to bang your head against.

— Ray Mairlot (@RayMairlot) October 13, 2017

When I first made this it wasn't immediately obvious where to start. Partly, that's because with AN, nothing is obvious, immediately or indeed ever. Nevertheless, I had heard enough about AN to know that 'Subprograms' might lead me to the effect I wanted. So there too, is where we will begin.

Here is the first section of AN node setup, which deals with scaling the objects:

Picture

A key concept of Animation Nodes is to think about repeatable chunks of work. Instead of having to animate each object individually, we create a chunk of work (or in AN terms, a 'Subprogram') that takes in one object and animates it. We can then take that chunk of work and repeat it for as many objects as we need.

The 'Loop Input' node is connected to the chunk of work and the 'Invoke Subprogram' node calls that chunk of work as many times as needed.

How does the 'Invoke Subrogram' node know how many times to run the 'Subprogram'? Well, that's what we'll set up first.

After adding an 'Invoke Subprogram' node and choosing 'New Subprogram'> Loop, we need to change the 'Loop Input' node to accept a different input. Ideally, we need it to take in a list of objects and perform an operation on each one. Luckily, that's as easy as clicking the 'New Iterator' button on the node and choosing 'Object List' from the list of available inputs.

You'll now see that the 'Invoke Subprogram' node has changed its input from being 'Iterations' to 'Object List'. Far more useful. The 'Loop Input' node now knows that I will be passing it a list of objects and that I want to run the 'Subprogram' for as many objects in the list.

Picture

As for the list of objects, we can do this with a regular Blender object group, so add all your spheres, or whatever confounded shape you've used, add them to a group (Ctrl+G) and name it something completely irrelevant, like 'Group.001'. You know, something that will be completely unintelligible when you come back to this project in a few months. I've been silly and named my group 'Objects in Torus', which almost sounds like a useful name. I'll change it later.

So to summarise, the 'Invoke Subprogram' node will be passed a group of objects and it's going to loop through the list of objects and animate them depending on what is connected to the 'Loop Input' node.

Add an 'Objects from Group' node, choose the group in the node's drop-down list that you just created and then connect its one output to the 'Subprogram's one input, like so:

Picture

That unnerving, unusual feeling, which you're hopefully feeling if my writing has served its purpose, is the feeling of starting to understand something, of making progress. A quite unusual feeling when first working with AN. Make the most of it, because it probably won't last long.

Now we're onto the actual animation, we want to be able to pull an individual object from that list. We already set up the iterator, and when we did this the 'Loop Input' node got a new output called 'Object'. We can now add any nodes we want to animate that individual object and the animation will get applied to all objects in our group, because the 'Object' output changes to a different object in the group each time the 'Subprogram' runs.

Here are the nodes, connected to the 'Loop Input' node that will actually animate each individual object:

Picture

The basic idea of how it's animating the object is it is looking at the location of two empties (one either side of the torus) and depending on how close the empties are to the individual object, it should be scaled somewhere between 0 and its original size. The empties are then animated closer and further away from the object which means the objects will then individually scale up or down.

To summarise the node setup above:
  1. Read in the 'Falloff' (a bit like Blender force fields, where there is an area around an empty in which objects are effected) - in this case we're specifically looking at the 'z' or '-z' direction of each empty and adding them together (so that both falloffs are considered). I think the falloff range is 0-1 so multiplying them together actually works better than adding so that the maximum values will never exceed 1 (1 x 1 = 1, obvs).
  2. Use the 'Evaluate Falloff' node to compare the current object's location and its distance to each of the empties (each object is only ever in range of one empty).
  3. Use the output of this calculation as the scale value for the object. As the objects have their scale applied, when the falloff is 1 the objects will be at full size, otherwise they will be scaled down.

On the left in the screenshot below, you can see the two empties selected, whose falloffs are compared to each object's location:

Picture

They're parented to a larger empty which is animated diagonally along the local 'z' axis as shown above. This is how the effect happens diagonally, as the 'Object Controller Falloff' nodes are set to read the local 'z' and '-z' axis respectively.

You can see on the right (above) a representation of the falloff, where in the centre it's lighter and the objects are full size, but if the empties move diagonally up and right, the imaginary dark falloff area will also move, start to cover the torus and cause the spheres to scale down.


Creating the 'Wave' Effect


The third and thankfully final part (come on, we're nearly at the end now) is to create the billowing wave effect. Here's the node network for the wave effect (I've removed the nodes that handle the scaling for the minute, just to make things a bit simpler):

Picture

The basic idea is that we are taking the original location of the object and using a 'sin' wave to animate it back and forth on the 'y' axis, adding in a bit of randomness for good measure along the way. The node setup above equates to this equation:
sin(xLocation - ((time + TimeOffset)/Speed)) * RandomNumber * Strength + OriginalLocation
For those that don't know, the 'sin' function produces a wave depending on the number fed to it. Seeing as we want an animated wave we need to pass in a constantly changing value, so we pass in the time value ('Time Info' node), offset it just so the wave starts on the frame I want (the 'Math' node adding 40 to offset by 40 frames), turn down the effect a bit ('Math' node dividing by 5) and finally we subtract the object's original 'x' location so that each object gets a slightly offset sin value (otherwise they would all move the same amount).

After that we multiply in a bit of randomness between 0.5 and 1 so they each move a bit more individually, turn down the overall effect by multiplying by a number less than one, add it to the original 'y' value (so they start from their original 'y' positions), combine the 'y' location with the original 'x' and 'z' locations, before it's finally used by the 'Object Transforms Output' node which sets the location for the current object. Phew.

It's possible, likely even, that this equation could be simplified, but such was the joy of finally getting something which resembled a result that I couldn't bear to touch anything and accidentally break it.


Add it all together


Now we've calculated the location and the scale we can add all the nodes together, producing this wonder:

Picture
Look at that big, lovely, seamless screenshot. It's almost as if I used some automated method to capture it.

Really, I should have added in a few more images, gifs or some other animated doodahs to break up those chunks of text, but golly gosh, I really couldn't be bothered; it took long enough just to write all of this without faffing about making nice illustrative, understandable and helpful images.

So there we have it, a completely clear, 100% explained, nothing vague, detailed, step-by-step guide of how I did it. Apart from all the parts I skimmed over and left to you, the avid reader, to figure out for yourselves. Which, in fairness to me - and I have been assured that I definitely deserve fairness - is only really the animating of the empties and the adding and connecting of the nodes.

Well done me. And well done to you for getting this far. But mainly well done me. Because let's be honest, it's me that's done most of the work in this transaction. I've had to use all 10 fingers to type, you've just had to use two eyes. Or whatever number of eyes you have available to you. Either way, regardless of the number of operational eyes, 10 fingers is more. No one's got 10 eyes.

Unless you're reading it in a group.

Bugger.


Ray.
Comments

The Shrinkwrap Modifier: A Hard-Surface Modeller's Best Friend

10/4/2016

Comments

 
This post is mainly about using the Shrinkwrap modifier for modelling, which is below, but there's also a quick update on some of my projects right at the end.

My Favourite Modifier


Before I started the 'Heartbreaker' project I probably wouldn't have said that the Shrinkwrap modifier is one of my favourite modifiers in Blender (not that anyone had actually asked me, or likely ever would). Maybe in the top 10, but only just. I would probably have gone for one of the classics, like the Subsurf or Mirror, you just can't go wrong with those two. However, that's all changed. If anyone ever asks me*, I will say my new favourite modifier, at least regarding modelling - which is what I'm doing most of the time - is the Shrinkwrap. It has become my go-to, problem solving, reliable friend.

*Which they wont.


Are You Insane? And What Does The Shrinkwrap Modifier Even Do?


No, I am not. A valid question (the second one), thank you (me) for asking. In its simplest form, the Shrinkwrap modifier is tasked with snapping the current object onto the surface of another object. It also has the ability to only snap specific vertices if you specify a vertex group.

Here we see a simple subdivided plane being shrinkwrapped to the surface of a sphere:
Picture
A simple, but I'm sure you'll agree, *Powerful* example.
I think the Shrinkwrap modifier was probably first created as a retopology tool, the snapping allowing you to easily create new, low-poly geometry, over your high-res model, without having to constantly think about manual snapping. Considering this, I'm not sure that 'Shrinkwrap' is actually the best name for it; maybe 'Snap' would have been better. The Snap modifier has a ring to it. But then, who am I to start renaming things? Sure, I was technically the best renamer in the area of Greater London in the years 1993 - 1998*, but I have no official certification for that, so I'll leave actual naming and any subsequent renaming to those that do.

*I retired from the gruelling world of competitive renaming undefeated and vowed never to return, due to the physical stress it caused my body.

How Does Retopology Tie-In To Hard-Surface Modelling? Are You Sure You're Not Insane?


It's not so much that retopology fits into hard surface modelling it's more that some hard-surface modelling scenarios and retopology share some common needs. Also, please stop asking if I'm insane.

There are two scenarios that can be very time-consuming when modelling:

  1. You have several meshes that all need to conform to the same profile (meaning surface curvature).
  2. You need to edit or add additional details to a curved surface.

This is very similar to what retopology requires and these two problems both happen to be the Shrinkwrap modifier's strength: conforming vertices to a specific surface.

That's All Well And Good, But Show Me Some Specific Examples


Please don't be so demanding. I've got some examples from 'Heartbreaker', the project I just literally won't shut up about.

The 'Heartbreaker' Iron Man suit has a tendency to have many separate panels that all conform to the same profile. Below, on the left, is the forearm, which is made of many pieces. They all have the same bulge and crease going through them, which would be time consuming to model manually. Instead, I built one continuous surface to describe the surface I want my mesh to conform to, shown on the right. All the pieces on the left conform to the profile of the mesh on the right (the Shrinkwrap target):
Heartbreaker also has many examples of detailing cut into curved panels. Cutting into curved surfaces is notoriously difficult as any sharpening edge loops on those details end up causing undesirable pinching, particularly at corners. It's also very difficult to perfectly maintain a curved surface while adding in new geometry.

Here, the head remains perfectly curved despite having cut details into it, thanks to good ol' Shrinkwrap:
Picture
Here is a wider view of the top of the head on the left, with its Shrinkwrap counterpart on the right:
The 'eyebrows' in the above image were excluded from the Shrinkwrap by adding all vertices apart from the eyebrow to a vertex group and selecting it on the Shrinkwrap modifier.

The Process


  1. Model a simple mesh that describes the curvature you want your mesh(es) to follow*.
  2. Add a Shrinkwrap modifier to the mesh(es) you want to conform to your Shrinkwrap object.
  3. Select the Shrinkwrap object as the 'Target' on the Shrinkwrap modifier.
  4. If you only want to Shrinkwrap part of your mesh, then create a vertex group that contains all the vertices you want to effect and select that vertex group on the modifier.
  5. If you want, repeat the previous steps to add multiple Shrinkwraps.

*If I've already started modelling something, but decide I need a Shrinkwrap, I will sometimes duplicate the object I'm modelling, simplify it, and use it as the Shrinkwrap object.

I also like to change the 'Maximum Draw Type' to 'Wire' in the 'Display' panel of the 'Object' tab in the 'Properties Editor' for the Shrinkwrap object so you can see the object you are modelling as well (shown below). Also, you may find it useful to turn on 'Draw All Edges', also in the 'Display' panel and 'Optimal  Display', on the Surbsurf modifier, if you're using one.
Picture
'Maximum Draw Type' set to 'Wire', 'Draw All Edges' and 'Optimal Display'.


When One Shrinkwrap Just Isn't Enough


Sometimes, creating a good enough Shrinkwrap object would be as complicated as modelling the original object, so not only will I sometimes use several Shrinkwrap objects (instead of one big one), but some of those Shrinkwrap objects have Shrinkwrap modifiers themselves. It's like needing to build scaffolding to be able to build more complicated scaffolding to be able to build the final object.

Here, for example, is the chest piece from Heartbreaker. It's probably the single most complicated piece in the whole suit, shown with all 9 of it's Shrinkwrap objects:
Picture
The key to this is vertex groups. Each Shrinkwrap object above is responsible for only part of the mesh.

Nobody's Perfect


Despite the unrivalled awesomeness of the Shrinkwrap modifier, it does have a problem, but it can be worked around quite easily.

When you're moving the vertices of an object that is Shrinkwrapped, what you're seeing is the vertices moving along the surface of the Shrinkwrap object. What's actually happening is that you're moving the vertices in 3D space. This causes the Shrinkwrap modifier to sometimes have a hard time determining which part of the surface the vertices should be on if the vertices are actually very far away from it in 3D space (which can happen when editing the mesh). The vertices will snap to the surface, but might not move smoothly. A quick fix for this is to press the 'Copy' button on the Shrinkwrap modifier to create a duplicate and then press 'Apply' on the copy. You have now applied the effects of the modifier and the vertices are now close to the surface again, allowing smooth movement.

The same 'Copy' and 'Apply' process also needs to be done if you find loop-cut-and-slide, vertex-sliding or other modelling tools start to position vertices weirdly. For example, with vertex-sliding, the vertices will slide dependant on where they are in 3D space, which isn't necessarily where they visually appear to be.

One other thing is that the Shrinkwrap modifier should probably be before any Subsurf modifiers you might have on the object. If you have a Subsurf first then you're giving the Shrinkwrap more vertices to play with than actually exist. This will only be problematic if you want to eventually apply all the Shrinkwraps on the object though.

The End, Finally


You may think using this technique only applies to specific objects or tasks, but I have found myself using it on many projects and I now can't do without it, so give it a try and let me know how it goes.

As a reward for getting to the end of this post (if you just scrolled all the way down without reading DO NOT LOOK BELOW AT THE REWARD, IT IS NOT FOR YOU), here is the entire 'Heartbreaker' suit with all 113 of it's glorious Shrinkwrap guides:
Picture
Embrace the Shrinkwrap modifier, love it, cuddle it, hold it at night, whisper sweet nothings into its ear and thank the gods it exists.

A Quick Update On Other Projects


I haven't got much done regarding 'Heartbreaker' so no update on that, other than I'm now working on fixing the upper-back, which I think is the last major part to be redone.

A quick update on 'Selective-Unhide', my unhiding add-on, is that it now supports not just Object Mode, but also Armature Edit Mode and Armature Pose Mode for hidden bones and bone groups and Mesh Edit Mode for hidden vertices:
Picture
Still a few things to do on it, I think, but they're relatively minor.


Ray.

Comments

Slider Puzzle Part 4 and the Big Project

17/5/2014

Comments

 
Well, it's slightly to my surprise that I hadn't actually posted the 4th part of my tutorial series on my blog:
It's been a few weeks since this video was released, the content of which has all but slipped from my mind, but I presume from the helpful title that it contains the actual animation of the pieces. After re-watching the intro I'm also informed that it contains some optimizations to make the code run a little more efficiently. So that's nice.

Blender Nation were also kind enough to feature the tutorial series in this post, which was a good boost to the views.
Not that views are all that count, but ultimately it's made to be watched.

Onto other things.

In a few blog posts I've mentioned the project I've been working on but have been somewhat reluctant to reveal what it actually is. I think the time is upon us (or just me if no one is reading) to reveal that my current Big Project is simply called 'Futuristic Car 2'. I'm sure the title will change but it refers back to the video I completed in the 3rd year of my computer graphics university course:

The premise was fairly simple, a futuristic car that has the ability to hover. At the time I was fairly pleased with the outcome, but, as can often happen with large projects, particularly when working on several at the same time, some compromises were made to the original idea without realising as the project progressed.

The car is made out of lots of small panels, a design change that was made after seeing 'suitcase suit' from Iron Man 2 but I didn't quite have time to animate a lot of the smaller panels and instead the transformation is a bit chunky. It was only a few months later, back in 2011, that I imagined the next version, a sleeker, sportier car more in keeping with my original design and yet keeping the idea of many smaller shifting panels.

Work on the project is slow and difficult, much of the time is spent on efficiency and workflow. Without careful management the many objects in the scene can become overwhelming. I'll cover my workflow in future posts. Hopefully.
 
If I remember.
 
Which I might.
 
Maybe.
 

Ray.
Comments

Slider PUzzle Part 3 and Bug Reporting

11/4/2014

Comments

 
Well, another week has shot by which means it's time for part 3 of my tutorial series:
I've also been working on my other main project. I haven't really spoken about it yet or shared anything about it other than that I've done some scripting for it. I'm still not ready to do that, maybe after this tutorial is out the way I can start sharing more about it.

But, as part of it I did come across what I thought was a bug in Blender, and I reported it as such. Reporting bugs for Blender is important. We use it, so it's in our benefit to improve it, even if all we can contribute is pointing out a problem in the hope that someone more skilled can fix it. It can be a bit of an alien concept to people who aren't familiar with open source programs, that there might be a way to contact the people who made a piece of software and get them to fix something or answer a question. Of course, it isn't limited to open source projects, I contact many services if I find an issue, open source just tends to promote it a bit more and, well, be a bit more open that it's a possibility. But whatever it is that you use, it again comes down to: Why wouldn't I want it fixed?

This is turning
into a post about bug reporting, really I just wanted to highlight the specific issue I had...

Turns out that what I reported wasn't actually a bug at all but a known design limitation. It's not exactly a bug because it's working as expected, even if the way it works isn't exactly ideal. It's annoying, but it basically means they, the developers, are aware of it, but can't currently change it.

I came across the limitation because I'm working with duplicated objects which all share the same object data (OD from now on) and they all need to share the same vertex groups. I thought that sharing/linking
OD would solve this, which it partially does. Apart from one slight problem. It turns out that the OD stores the vertex groups and their weights but it doesn't store their names. The names can be unique for each object that shares OD. So two objects which share OD will have the same vertex groups and they'll be linked, but they could be named completely differently.

Which is....confusing.

Edit
one vertex group called 'group 1' on one object and 'group 2' might be edited on the other object if you've renamed a group on one object but not the others with linked data...

Cue a series of scripts to try and manage all this. Haven't quite fixed it all yet, have to work out which vertex groups aren't being used by modifiers so I can clean it all up a bit and maybe have some global counter which handles the naming of any new groups.

Anyway, I don't regret reporting it as a bug even though it's technically not. I've at least come away knowing how it works, thanks to Campbell Barton (a Blender developer) and I don't think it does any harm letting the developers know that people are still finding this is an issue. It's also far better to have reported it than potentially be trying to work out workarounds when a simple report could have fixed it.

Better safe than sorry.


Ray.
Comments

Slider Puzzle Part 2 and more scripting

6/4/2014

Comments

 
Here is the second part of the Slider Puzzle Tutorial, this part focuses on unwrapping and texturing the grid:
I think I just need to confirm that while I said there wouldn't be any more tutorials on a regular basis, that only comes into effect after this tutorial series is over. There are 2 more parts of this current tutorial still to be released, after that, it's a bit less certain.

Anyway, onto more coding...


I've found that since having worked on bigger python projects, smaller scripts are far quicker to write having become far more familiar with the code. I've always found myself writing little mini scripts for things like enabling/disabling Subsurf modifiers for all objects in a scene, so for my current project I decided to create a little toolset that I can eventually develop and use across all my projects.
Currently all it does is the aforementioned Subsurf on and off along with controlling the Shrinkwrap modifier in a similar way. This is quite specific to the project I'm doing where it's really useful to control just these modifiers, but I'd hope in the future to be able to dynamically search the scene for all modifiers so they can all be controlled in this manner for more general projects.
Picture
The layout is a bit of a hack at the minute as I'm kind of forcing a 2 column menu to look like a panel. Eventually as I add more tools I'll probably collapse the modifier tools into proper submenus.

Another cool thing I found was the ability to have an operator set a custom property when it runs. So I can use the same operator to make both the modifiers visible and invisible. On line 7 you can see I define a new property within the operator. To make sure I can access it I pass 'self' and 'context' into both the execute function and the function that has my main code on lines 9 and 10. It's with 'self' that you access the property, so I haven't yet experimented if 'context' is actually needed:
Picture
Then you can access the operator property with '.propName' after the normal operator call and set it's value:
Picture
You can then access the property with 'self.propName':
Picture
Now I just have to work out how to set multiple arguments with an operator call...


Anyway, have to actually do some work now instead of just writing about it. Part 3 of the Slider Puzzle tutorial is out on Tuesday.


Ray.


Ps. I hope to have proper embedded code working soon.
Comments

Creating the grid and the end of tutorials

29/3/2014

Comments

 
Well, it's certainly been a long time since my last video. Here's the first part of the tutorial that accompanies it:
I had actually planned on stopping doing tutorials, or at least 'ramping down'. I got a job in November (unfortunately not related to 3D or graphics), so my spare time is a little more precious now.

In the past year, without realising it, the effects I make have steadily becoming more complex as I attempt more ambitious ideas. I think it's natural that that should happen but it means the tutorials have become a lot longer to accommodate all the extra processes and all of this has started to take up a great deal of my time. The effects have gone from taking a few days to complete to needing about a week, mainly of troubleshooting, and the tutorials have steadily crept up to the 1hr mark (edited down from 1hr 40min of recorded material).

Because of this I've actually done very few modelling projects in the past year and for someone who wants to be a 3D modeller, this isn't great. So, all my time has to be focused on modelling now and tutorials have to take a back seat for the minute. This isn't the end of the tutorials, but certainly they can't be a priority any more and this tutorial marks the end of any frequent videos.

Knowing that this would be the last tutorial and frankly, looking forward to getting it out of the way so I could continue modelling, I certainly hadn't bargained on this being the most complex tutorial I've ever done. Longer, harder ideas to explain, harder to edit, everything was more complex.
And it took a whole lot of time to complete.

Turns out explaining programming is pretty difficult, some of the concepts start to seem a bit abstract when you sit down and try to explain them so I had to create extra graphics to try and visually explain them and extra annotations for things I'd simply forgotten to mention. Suffice to say that with all this added up, the tutorial was long enough that it seemed beneficial to split it up, so this video is part 1 of 4, each to be released weekly.


It's a shame, because I like coming up with projects for tutorials, I even started thinking about the next project I wanted to do. But, like I said, that has to take a back seat. If I get some time to work on it, which I hope I do, then great.

Ray.

Comments
<<Previous

    RSS Feed

    Categories

    All
    Animation
    Blender
    Compositing
    Flash
    Geometry Nodes
    Heartbreaker
    Hmhb
    Image
    Macro Maker
    Nodes
    Programming
    Python
    Rollercoaster
    Tutorial
    Unity
    Vfx
    Video


All images and videos copyright © Ray Mairlot, 2022.
None of the content on this site is to be used without my permission.
Powered by Create your own unique website with customizable templates.
  • Gallery
  • Blog
  • Store
  • Contact
  • About