Archive for the ‘Uncategorized’ Category

City Scanner scene

October 10, 2016

Had a bit of fun making a scene for my Half Life 2 city scanner.
Will do some break downs of the scene here on my blog at some point 🙂

Advertisements

Shopping for masks in Houdini

January 20, 2016

Houdini pun there, don’t worry if you don’t get it, because it’s pretty much the worst…

In my last post, I talked about the masking effects in Shangri-La, Far Cry 4.

I mentioned that it would be interesting to try out generating the rough masks in Houdini, instead of painting them in Modo.

So here’s an example of a mask made in Houdini, being used in Unreal 4:

VortUE4Houdini.gif

Not horrible.
Since it moves along the model pretty evenly, you can see that the hands are pretty late to dissolve, which is a bit weird.

I could paint those out, but then the more I paint, the less value I’m getting out of Houdini for the process.

This is probably a good enough starting point before World Machine, so I’ll talk about the setup.

Masky mask and the function bunch

I’ve exported the Vortigaunt out of Modo as an Alembic file, and bring it into Houdini.
Everything is pretty much done inside a single geometry node:

MaskGen_all

The interesting bit here is “point_spread_solver”. This is where all the work happens.

Each frame, the solver carries data from one vertex to another, and I just manually stop and bake out the texture when the values stop spreading.

I made the un-calculated points green to illustrate:

VortGreen

A note on “colour_selected_white”, I should really do this bit procedurally. I’m always starting the effect from holes in the mesh, so I could pick the edge vertices that way, instead of manually selecting them in the viewport.

The solver

MaskGen_point_spread_solver

Yay. Attribwrangle1. Such naming, wow.

Nodes are fun, right up until they aren’t, so you’ll often see me do large slabs of functionality in VEX. Sorry about that, but life is pain, and all that…

Here’s what the attrib wrangle is doing:

int MinDist = -1;

if (@DistanceFromMask == 0)
{
	int PointVertices[];
	PointVertices = neighbours(0, @ptnum);

	foreach (int NeighborPointNum; PointVertices)
	{
		int success             = 0;
		int NeighborDistance    = pointattrib(
						1, 
						"DistanceFromMask", 
						NeighborPointNum, 
						success);

		if (NeighborDistance > 0)
		{
			if (MinDist == -1)
			{
				MinDist = NeighborDistance;
			}

			MinDist = min(MinDist, NeighborDistance);
		}
	}
}

if (MinDist > 0)
	@DistanceFromMask = (MinDist + 1);

Not a very nuanced way of spreading out the values.

For each point, assuming the point has a zero “distance” value, I check the neighboring points.
If a neighbor has a non-zero integer “distance” value, then I take the lowest of all the neighbors, add one to it, and that becomes my “distance” value.

This causes the numbers to spread out over the surface, with the lowest value at the source points, highest value at the furthest distance.

Integers –> Colours

So, the vertices now all have integer distance values on them.
Back up in the mask image, the solver promotes the Distance value up to a Detail attribute, getting the Max Distance of all the points.

In the wrangle node under that, I just loop through all the points and divide each point’s Distance by the Max Distance, and use that to set the colour, or I set it as green if there’s no distance value:

if (@DistanceFromMask > 0)
{
    @Cd = float(@DistanceFromMask - 1) / float(@DistanceFromMaskMax);
}
else
{
    @Cd = {0,1,0};
}

So that produces the gif I showed earlier with the green on it.

Colours –> Textures

Time to jump into SHOPS. See? This is where my awesome title pun comes in.

As simple as it gets, vertex Colour data straight into the surface output:

Material

In my “Out”, I’m using a BakeTexture node to bake the material into a texture, and I end up with this:

vortigaunt_mask_houdini

Conclusion

Bam! Work is done.
Still wouldn’t have been much point in doing this on Shangri-La, because painting masks in Modo is super quick anyway, but it’s fun to jump back into Houdini every now and then and try new things.

Has led to some other interesting thoughts, though.

  • For Shangri-La, we could have done that at runtime in a compute shader, and generated the mask-out effect from wherever you actually shot an arrow into an enemy.
    That would have been cool.
  • You could probably use Houdini Engine to put the network into UE4 itself, so you could paint the vertex colours and generate the masks all inside UE4.
  • You could do the “erosion” part in Houdini as well, even if you just subdivide the model up and do it using points rather than run it in image space (to avoid seams). Might be hard to get a great resolution out of it.
  • You could do an actual pressure simulation, something along the lines what this Ben Millwood guy did here. He’s a buddy of mine, and it’s a cool approach, and it’s better than my hacky min values thing.

Dead Space fan art: Necrotle

October 31, 2015

Necrotle

Right in time for Halloween, meet a Necrotle!
That’s a Dead Space Necromorph turtle, fyi.

I started on this guy about 5 years ago, while I was working at Visceral Games in Melbourne. I wasn’t on the Dead Space project(s), I just felt like doing some fan art, and decided to come up with the most silly idea for an animal Necromorph I could think of (a giraffe was also in the plans, at one point…) 🙂

As with many of my home projects, I got sick of it and shelved it for a while. Decided a few weeks ago to resurrect the little fella!
And now I’m sick of looking at it again, and I’m calling it done 😉

Started with a very basic sculpt in 3dcoat, then modeling, additional sculpting, texturing, rendering in Modo.

Houdini? Who don’t-y?

June 24, 2015

I’ve been waiting about a year to use that blog post title. Don’t judge me…

I bought Houdini Indie about a year ago, and up until a few months ago I hadn’t used it.
In the last few months, I’ve started learning fracturing and pyro effects (smoke, fire, etc).

In this video, I’m fracturing an object and generating “smoke” (dust is the intention, but I haven’t added particles to it, so it definitely looks like smoke).

Brief background on Houdini fluid sims

Very brief, because I’m still learning 😛

In Houdini, you create volumetric fields of data that drive fluid simulations, much like in other software like FumeFX.

For a smoke sim, you can get away with just Density and Heat. The Density controls how much smoke gets added per frame (although like everything in Houdini, this is a loose definition). The Heat will move the smoke around using gas pressure simulations.

I’m also using a Velocity field, because it’s one way of getting the pieces of my fractured geometry to disturb the smoke as they move through the fluid.

Each piece of the fractured geometry is glued to pieces next to it using “glue constraints”. These break either when I manually break them, or when a certain amount of force is applied to them.

The goal of this scene

There are plenty of ways of setting up the Smoke Density, and the most common one I’ve seen is just adding Density to the fluid in places where geometry is moving at a certain speed.

Instead of that, I wanted to add dust when a constraint breaks (based off the mass of the pieces), and only add it to the sim if the piece is moving above a certain speed.

The end results are not a great deal different, but there’s a few things I like:

  • Small pieces can shed all their dust before they hit the ground. You don’t end up with streamers of dust all the way to the ground just because something is moving fast.
  •  There’s good variation in the amount of smoke/dust that pieces generate, due to the mass being factored in.
  • A group of pieces can fall off as a chunk, generating some smoke for a few frames. When that chunk hits the ground and breaks again, the broken constraints can generate more smoke. This could look really nice if I had a more complicated scene setup 🙂

The setup

This is what my scene looks like:

OverallNetwork

There is a tube that I fracture, a ground plane, two simulations (fracturing and the smoke fluid sim) and “SmokeSource” which is where I generate the fields for the fluid simulation.

Tube object (fracture setup)

I won’t go too much into the Fracture setup, because it’s pretty standard, but here’s what that network looks like:

TubeObjectNetwork

So the top bit does a voronoi fracture on the geometry, the middle bit adds a “depth” value attribute, which is how far each point is from the original surface of the object (I intended to use this for something, but then… didn’t).
The left side sets up which pieces of geo are active, using a box to select the ones I want (everything except the base of the cylinder, basically). The right side creates the glue constraints.
There’s a few File nodes to cache things out to disk.

Most of this is set up through standard shelf tools.

Collapse Sim

CollapseSimNetwork

Again, pretty basic stuff, most of this is created when you use shelf tools to setup a sim.
The only interesting bits in this are the “Geometry Wrangle” node at the top, and a few things I added to the “Remove Broken” solver.

Geometrywrangle_dust

This  is where I’m doing most of the dust setup work (although probably shouldn’t, more on that later…).

Here’s the VEX code:


vector c = point("op:/obj/tube_object1/OUT_ACTIVEPOINTS", "Cd", @ptnum);
i@active = (int)c.r;

float DustPerKilo = 0.2;
float DustLiberatedPerMetrePerSecond = 350.0;
float MinimumSpeedForDustLiberation = 0.4;
float MaximumSpeedForDustLiberation = 6.0;
float LiberatedDustDissipationRate = 60.0;
string GlueConstraintPath = "op:/obj/CollapseSim:Relationships/glue_tube_object1/constraintnetwork/Geometry";
string GeoPath = "op:/obj/CollapseSim:tube_object1/Geometry";

int NumPieceAttributes = 2;

for (int PieceCount = 1; PieceCount <= NumPieceAttributes; PieceCount++)
{
	/*
	* This is horrible, and would break down for constraints that had more than 2 pieces...
	* Attributes are "Piece1, Piece2" the first time through. "Piece2, Piece1" the next
	*/
	string AttributeToFind = "Piece" + itoa(PieceCount);
	string AttachedPieceAttribute = "Piece" + itoa((PieceCount%NumPieceAttributes) + 1);

	// First, get the number of glue constraints that have this piece as "piece 1"
	int NumberOfGlues = findattribvalcount(GlueConstraintPath, "prim", AttributeToFind, @ptnum);

	int ConnectedPieces[] = {};

	for (int Count = 0; Count < NumberOfGlues; Count++)
	{
		int Success;
		int CurrentGlueConstraintIndex = findattribval(GlueConstraintPath, "prim", AttributeToFind, @ptnum, Count);

		int PieceVertIndex = primattrib(GlueConstraintPath, AttachedPieceAttribute, CurrentGlueConstraintIndex, Success);
		string PieceName = pointattrib(GlueConstraintPath, "name", PieceVertIndex, Success);
		string Bits[] = split(PieceName, "/");
		ConnectedPieces[len(ConnectedPieces)] = atoi(re_find("([0-9]+)", Bits[1]));
	}
}

int RemovedPieces[] = {};
float RemovedPieceMass = 0.0;

// Check to see if any constraints have been removed
foreach(int PreviousPieceIndex; i[]@aConnectedPieces)
{
	int found = 0;

	// Search current array against last, etc
	foreach(int CurrentPieceIndex; ConnectedPieces)
	{
		if (CurrentPieceIndex == PreviousPieceIndex)
		{
			found = 1;
			break;
		}
	}

	// For every broken constraint, add some dust    
	if (found == 0)
	{
		RemovedPieces[len(RemovedPieces)] = PreviousPieceIndex;

		int Success;
		RemovedPieceMass = RemovedPieceMass + pointattrib(GeoPath, "mass", PreviousPieceIndex, Success);
	}
}

/*
* Increase the dust amount if we have removed some pieces and use the mass
* of those pieces to scale how much dust is generated
*/
if (RemovedPieceMass > 0.0)
{
	@DustAmount = @DustAmount + (DustPerKilo * RemovedPieceMass);
}

f@VelocityMag = length(@v);

// Disperse the freed up dust a little each frame
if (@DustLiberated > 0.0) @DustLiberated = max(@DustLiberated - LiberatedDustDissipationRate, 0.0);

/*
* Based off the speed of this piece, transfer some
* of the Dust to "liberated".
* This allows the dust to be used up over a number
* of frames, faster for fast moving pieces
*/
float VelocityMultiplier = (f@VelocityMag - MinimumSpeedForDustLiberation) / (MaximumSpeedForDustLiberation - MinimumSpeedForDustLiberation);
VelocityMultiplier = clamp(VelocityMultiplier, 0.0, 1.0);

float DustAmountToLiberate = VelocityMultiplier * DustLiberatedPerMetrePerSecond;
DustAmountToLiberate = min(DustAmountToLiberate, @DustAmount);
@DustLiberated = @DustLiberated + DustAmountToLiberate;
@DustAmount = @DustAmount - DustAmountToLiberate;

addvariablename(geoself(), "DustLiberated", "DUSTLIBERATED");

// Store the connected pieces as an attribute (used when comparing between frames)
i[]@aConnectedPieces = ConnectedPieces;

The first loop is pretty ugly to look at. It used to be two separate loops with a bunch of copy-pasted code, not sure it’s any better now that I “cleaned” it up.

Anyway, this code searches through all the Constraints in the scene, and finds any constraint that is connected to the current piece

For each Constraint it finds, it keeps track of the piece of geometry that this one is connected to, and puts it into a “connected pieces” array.

The “connected pieces” array is stored on the geometry as an attribute. Each frame the sim runs, you have access to the previous attribute values in this Geometry Wrangle.
If a piece was connected last frame, but not this frame I use the mass of the no longer connected piece to add a “DustAmount” to our current piece.

Each frame I transfer a bit of the DustAmount (if there is any) to “DustAmountLiberated” based on the velocity of the piece. This “DustAmountLiberated” is what I’m using to create the smoke density.

Phew! So not exactly neat code, sorry about that, but hopefully that makes sense.

Remove Broken solver

CollapseSim_RemoveBrokenNetwork

Nothing very exciting here, but each frame I have a sphere that expands that deletes constraint primitives.
It leaves the points alone, because I still need to look up the points for constraints that have been broken, so keeping the points makes life easier 🙂

After a bunch of frames, it looks like a packman cylinder. I think that warrants a screenshot:

Constraints

DeletePrimitivesBasedOnPoints

This is another attribute wrangle, which checks to see if the constraint is marked for delete, or if either point in the constraint is marked for delete (by the big sphere of death).
If any of that is true, the whole primitive if marker with the “ToDelete” attribute.


int Point1 = primpoints(0, @primnum)[0];
int Point2 = primpoints(0, @primnum)[1];

i@Point1Delete = point(0, "StuffToDelete", Point1);
i@Point2Delete = point(0, "StuffToDelete", Point2);

i@ToDelete = (i@ToDelete || i@Point1Delete || i@Point2Delete);

Smoke Source

SmokeSourceNetwork

This network imports the results of the Collapse sim, so that it can generate the fields that I need to pass to the Smoke Simulation.
I mentioned that I’m using heat, density and velocity, but I’m actually just using the density as heat. That makes no sense, but I didn’t bother coming up with a better plan 🙂

Anyway, the Density is generated just from chunks of geo with “liberated dust” amounts.
The Velocity is generated from all geometry pieces:

SmokeSourceParts

The Velocity field is kinda cute.

SmokeVelocityPreview

Network wise, there’s not a lot fancy here. A little bit of hackery to avoid errors on the first frame, because the DustLiberated attribute doesn’t exist at that time (hence the switch node, which just uses a condition of “if we are on the first frame do X”, where X is ignore all the geo).

Probably worth noting that for the density, I’m using points scattered on the surface of the geometry, but I’m deleting the exterior faces, because they are never connected to anything 🙂

Smoke Sim

SmokeSimNetwork

Nothing very exciting here either, pretty much a standard pyro shelf setup with a wind node thrown in.
I also added a switch node so I could quickly change between a few fluid grid setups for quick previews.

Well that was fun!

So that’s it! Sorry it was a bit of a wall of text.

This was a fun exercise, although it took me a long time to sort this all out, it really helped me learn more about pyro sims, and Houdini in general.

Aside from making an actual scene to destroy, creating particles for the dust, and tweaking the fluid sim settings to make it better, there’s a few things I thought of half way through this that I’d like to try:

  • Use surface area instead of mass to drive the amount of dust.
  • Combined with the above, instead of generating the dust all over the piece of geometry, I could convert the two pieces of geo to volumes, intersect those volumes and generate the dust only on the intersecting places.
  • The turbulence looks horrible. Yuck. It looks like the smoke is wriggling about in jelly (or jello for those living in America)
  • I think I could probably move the dust calculations into SmokeSource. Currently, if I want to tweak dust amounts, I need to re-sim just about anything, which is annoying.
  • Non linear reduction of dust amount might be nice, sometimes the dust cutoff is a bit sudden

So… Are you still doing Unreal and Half Life inspired stuff, or did you just get bored and wander off?…

Yeah. Well.
So I was intending to use Houdini to do a bunch of stuff for that, but we’ll see 🙂

The first thing I started trying out (when I had no idea what I was doing) was smashing up my chamber:

Orange is the new “MetalWearDirtDentMaterialInstance_01_a”

September 9, 2014

Naming conventions, ha!
That’s the beauty of home projects, I can get away with it…

Annnnyway, just a quick update this time.
I finally got around to unwrapping the floor panels and rails in the scene. In doing so, I think I’ll need to do a fair bit more work on where the panels join the rails (rubber strips or something, maybe). Also, the outer panels are way too big, coming in at about 5 and a half Freemans, so I’ll need to break the up / re-design them.

Still, it’s given me the fun opportunity to take my dirt metal material, and re-use it on a few new material, so I now have some shiny rails and floor panels:

UE4 orange metal panels

UE4 orange metal panels

Mari 2.6 out

April 4, 2014

Mari 2.6 is out.

Texture transferring tool looks good! 🙂

http://www.thefoundry.co.uk/products/mari/latest-mari-release/

Still plugging away

May 23, 2010

Still working my way through learning more about Modo. I’ve been having a lot of fun with duplicating along curves, beziers, etc, at work. Still really miss having a Stack like in Max, though, and of course nothing really compares to Max’s path deforming, lofting, etc. Well, nothing I’ve found yet, anyway, there’s pleny of software out there 🙂

I’ve started trying to teach myself 3d sculpting, too, although I think that will be a long long term goal. Picked up a great sculpting book at the Weta workshop a while back: “Mastering Portraiture: Advanced Analyses of the Face Sculpted in Clay”. It is quite good, very in depth.

If I do anything that doesn’t look like a lumpy ugly mess, I’ll post it up 🙂

This time, for sure

October 10, 2009

Time for something slightly better than just “woo woo woo, I have a blog”…

So I’m playing around with Modo at the moment. For the last year or so, I’ve been trying to build up a library of licensed software at home. I’m not sure if I will ever use any of it for commercial work, but I had always told myself when I was a student that I would make an effort to purchase everything I could when I was in “the industry”.

Anyway, so far I’ve got myself Photoshop CS4, Modo, and Mudbox. Strangely, dishing out a large wad of cash on software has encouraged me to actually use it all a bit more at home 🙂 I’ve thrown up some of my work in progress on the Luxology website, linked in from a gallery here. If I come up with anything useful, I’ll put it up here.

Blogging!

July 29, 2009

Figured it was about time I did one of these 🙂