Jump to content
Atom

Orient Along Organic Surface?

Recommended Posts

I have this sweeping kind of hull section that is all quads. I am scattering some geometry to the center of each primitive. I know about the @orient attribute, but I don't know how to construct it to conform to an organic style shape.

How can I make my scattered geometry shapes align correctly to the organic topology?

Currently I have placement working, but rotation is off.

Untitled-1.jpg

Share this post


Link to post
Share on other sites

Hey Atom, could you try out the attached file? See if this approach would work for you?

I basically processed the incoming mesh in a wrangle. It generated the center points, and directly assigned the vector Up and N attributes to each point for alignment.

prim_center.gif.613892548ca58e410e57e78db09c083b.gif

image.png.fe3e24d33c99245518b9b6eabf52fbc5.png

* Just replace the GEO mesh with your mesh. Or in the case of the above GIF, I used the Test Geometry Pig Head, scaled to 7.5 *

H16.0.745 Indie -prim_center.zip

 

Share this post


Link to post
Share on other sites

Thanks Jeff,

That does get my rotation more into the ball park of what I am looking for. I found that deriving direction from point 0 and point 3 gives a better alignment on my particular mesh. But then I am boldly assuming that all primitives are quads (which is my current case). Next step is to leverage the area of the primitive to set @pscale and skip tiny primitives. Although it would be nice to somehow stretch my stamped geo to more closely match the size of the host primitive, such as those long thin strips.

Is there a vex bbox function for primitives?

Untitled-1.jpg

Edited by Atom

Share this post


Link to post
Share on other sites

primuv already is basically a 2d representation of the primitive's footprint. a not-aligned bounding box of each primitive can also be found in the primitives intrinsics called "bounds". if you want to copy and squeeze models onto primitives I would create the copies first, create a "copynum"-attribute and distribute the models with something like this:

vector bbox = relbbox(0, @P);
int prim = point(0, "copynum", @ptnum);
float height = sqrt( primintrinsic(1, "measuredarea", prim) );
@P = primuv(1, "P", prim, set(bbox.x, bbox.z, 0) );
@P += prim_normal(1, prim, {0.5, 0.5, 0}) * bbox.y * height;

The bounding box from line 1 is stretched across the primitives from line 2 with primuv in line 4. The approximate height of the copies gets derived from the primitives area size in line 3 and is raised along the primitives normals in line 5.

 

copy_on_prims.hipnc

copy_on_prims.png

Edited by konstantin magnus
added screenshot
  • Like 6

Share this post


Link to post
Share on other sites

That is an absolutely brilliant approach Konstantin! Reading the code is like hearing a very beautifully composed song! Thank you so much :D

Share this post


Link to post
Share on other sites

Thanks for the example file Konstantin. That is a really nice implementation. I have been trying to figure out how to modify it.

Is there a way to skip some primitives?

Is there a way to have a border or edge around each copy? (i.e. inherit pscale)

Also, I have over 40 different nurnie, doodads, greeble objects that I want to scatter across my ship hull. In my previous setup I was going to leverage stamping a switch index, but in your setup I am not exactly sure how to achieve that same result...

Untitled-1.jpg

Edited by Atom

Share this post


Link to post
Share on other sites
7 minutes ago, Atom said:

Is there a way to skip some primitives?

Just blast them before counting.

9 minutes ago, Atom said:

Is there a way to have a border or edge around each copy?

Apply a fit01() function on bbox.

13 minutes ago, Atom said:

I have over 40 different nurnie, doodads, greeble objects

Make sure your copies have ongoing "copynum" attributes.

  • Like 1

Share this post


Link to post
Share on other sites

great...now, could someone please explain to me why they aren't symmetrically consistent ?

Symmetry.jpg

Share this post


Link to post
Share on other sites
1 hour ago, Noobini said:

could someone please explain to me why they aren't symmetrically consistent ?

Has to do with the winding of the underlying geometry. Just display the vertex numbers of the target geometry and you will see it's the polygons that are not consistent. It works fine on primitive objects, though (tori, grids etc.).

Edited by konstantin magnus

Share this post


Link to post
Share on other sites

 

19 hours ago, konstantin magnus said:

Make sure your copies have ongoing "copynum" attributes.

I guess I still don't understand how the copynum works. The Copy node in the setup has only one input. How would I provide access to my other shapes without a switch? The input does not work like a merge, if I plug a new shape into the Copy, I lose the old shape.
 

 

Untitled-1.jpg

Edited by Atom

Share this post


Link to post
Share on other sites

Hey Atom, I took another stab at it. Here's probably one approach to do it.

image.png.4bad50880854c0c3b8be8efd0eafcfdb.png

The idea is to create the needed number of copies for each of the pighead's primitives.
So for example, if the pighead has 300 primitives, and we have 3 doodads (sphere, box, teapot) to scatter.. we need to have 100 spheres, 100 boxes, and 100 teapots to create.
Then inside the loop, I also offset the copynum that is assigned.

I still have a couple of other approaches that I would like to try, but for now this might do. :D

H16.0.745 Apprentice - copy_on_prims_v2.rar

Edited by galagast
  • Like 1

Share this post


Link to post
Share on other sites

I finally understand what Konstantin's code is doing. With that I was able to use it as fix up after a standard CopyStamp node. Basically just set @P to {0,0,0} on the right side of the CopyStamp, then let Konstantin's fixup code migrate all the copies to their correct locations. This is slow on high poly count objects but it is a start. Next step would be to implement it as instances to recover some performance.

tech_pig.gif.9295b1f3f6795bf9324f420302f6f70b.gif

Untitled-1.jpg

ap_stretch_copy_to_primitve_area.hiplc

Untitled-1.jpg

Edited by Atom

Share this post


Link to post
Share on other sites

Cool Atom! Yours is now much simpler compared to the last file I uploaded :D

It makes much more sense to generate the copynum from the primitives themselves!

Share this post


Link to post
Share on other sites

Really great, educational stuff on here - thanks to everyone for sharing. I've been trying to look at the flow problem on its own i.e. the fact that primuv is dependent on the winding order of the underlying poly and hence the direction of the fitted object is hard to control (without changing that winding order). Here's a scene that uses anim's (amazing) setup from the linked thread and some additional flowlines to try and conform the fitted geometry to a flow that snaps to the polygon directions. Some very, very coarse coding going on but with some more love (and optimisations) it might make for a nice hybrid. It's very slow at the moment probably because of the copy stamping!

flow fit.hipnc

flowA.gif

result.jpg

  • Like 2

Share this post


Link to post
Share on other sites

Thanks again for the example files!

I have added some controls to the system. I can discard some based upon area and increase height of the distributed parts/pieces. I am still trying to add a border around the pieces which kind of works. But when I increase the border the parts/pieces grow from the corner of the primitive. I would like them to remained centered on the primitive instead.

I know it is related to the bbox.x and bbox.z values but I am not sure how to calculate the correct result so the part/piece ends up in the center.

vector bbox = relbbox(0, @P);
int prim = point(0, "copynum", @ptnum);
float height = sqrt(primintrinsic(1, "measuredarea", prim));
float range = ch("range");
float range_div2 = range * 0.5;
float x = fit01(bbox.x, 0, range)*range;
float y = fit01(bbox.y, 0, range);
float z = fit01(bbox.z, 0, range)*range;
@P = primuv(1, "P", prim, set(x,z, 0) );
@P += prim_normal(1, prim, set(range_div2, range_div2, 0)) * y * (height * ch("mult_height"));

 

tech_ship.gif

ap_stretch_copy_to_primitve_area_110717.hiplc

Edited by Atom

Share this post


Link to post
Share on other sites
vector bbox = relbbox(0, @P);
int prim = point(0, "copynum", @ptnum);
float height = sqrt(primintrinsic(1, "measuredarea", prim));
float range = ch("range");
float range_div2 = range * 0.5;

float x = fit01(bbox.x, range, 1-range);
float y = fit01(bbox.y, 0, 1);
float z = fit01(bbox.z, range, 1-range);

@P = primuv(1, "P", prim, set(x,z, 0) );
@P += prim_normal(1, prim, set(range_div2, range_div2, 0)) * y * (height * ch("mult_height"));

@Atom if you fit between range and 1-range it scales from the centre..

@galagast didn't realise you'd already solved it!

Edited by julian johnson
Jeff already posted solution!
  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×