Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

Thread Tools Search this Thread Display Modes
Old 02 February 2013   #1

I have the following problem: I want to write a scatter tool where I can randomly distribute objects on the surface of an selected object. The Object can be everything, like scatter hairs on the surface of a dog or something like that. Can anyone give me a hint how I can do this. I also want do avoid collisions in an efficient way.
My plan would be the following:
Scatter objects on faces and then rotate them dependent on the normal vector of the face
But how can I avoid collisions, or is there any more efficient way than using the normal vector? How does the hair plugins and grass plugins work? Thanks a lot
Old 02 February 2013   #2
You could use PFlow and use particle positions and normals. I'm not sure how you could do efficient collision checking tho. Maybe you can use separation in Position Object, but it only works if you know size of your objects. I was going to do my own scatter tool with pflow but never got time to finish it. Here's some testing i did:

( delete objects local sp = Sphere radius:50 segments:32 local pf=pf_source logosize:10 name:"pf" Quantity_Viewport:100 particleFlow.beginEdit() local rendParticles=renderParticles() pf.appendAction(rendParticles) local pCount = 40 local evt = event() local birthAction = birth amount:pCount emit_start:0 emit_stop:0 local positionObjectAction = position_object emitter_Objects:#(sp) location:3 Random_Seed:(random 0 10000) local speedBySurfaceAction = speed_by_surface surface_objects:#(sp) direction_type:0 local rotationAction = rotation direction:3 euler_y:90 local speedAction = speed speed:0 particleFlow.endEdit() evt.appendAction birthAction evt.appendAction positionObjectAction evt.appendAction speedBySurfaceAction evt.appendAction rotationAction evt.appendAction speedAction pf.appendInitialActionList evt completeRedraw() for i=1 to pf.numParticles() do ( local pos = pf.getParticlePosition i local tm = pf.getParticleTM i local t = teapot pos:pos radius:5 t.transform = tm ) completeRedraw() )
Old 02 February 2013   #3
particle flow is a possibility but I don't particularly like the way it handles node orientation and random rotations (oh and Directx materials), though you can steal some of it's core methods....

maxsdk\samples\ParticleFlow\Actions\PFActions_Glob alFunctions.cpp

the helpful functions (among others) are

bool ClosestPointOnMesh(const Point3& toPoint, Mesh* mesh, Point3& worldLocation, Point2& localCoords, int& faceIndex, float& dist2) bool IsPointInsideMesh(Mesh* mesh, Point3 p)

though c++ they pretty easy to port to mxs if you need to....

other approaches you could consider is using some kind of voxel ray thing with RayMeshGridIntersect
as for avoiding collisions thats a tough one and potentially very slow. particle flow lets you set a min separation distance which is the most simple method available, which is fine with stuff like hair or grass as you will never be close enough to tell if things are slightly amiss.

Last edited by Klunk : 02 February 2013 at 09:34 AM.
Old 02 February 2013   #4
ok thanks I will try.
Old 03 March 2013   #5
Hi, there is an algorithm called stochastic search. You can use the simplest stochastic search to avoid collisions. After the code allocates positions you can write the part of the code that rotates your object. The following code allocates positions for boxes inside a user defined grid. For an arbitrary surface you have to write something more versatile, but the logic of the placement could still be useful. It is also recursive so be careful:

seed = 12345 myBoxes = #() num = 20 tolerance = 1.0 for i in 1 to num do ( myBoxes[i] = box width:2 height:2 length:2; b = myBoxes[i]; = "MyBox_" + i as string sv = 0 -- safety valve to avoid infinite loops range1 = 50--user defined range for the grid range2 = 50 --user defined range for the grid overlap = true -- examines weather a box overlaps with another while overlap do ( NewPosX = random -range1 range1 --get a random x position NewPosY = random -range2 range2 --get a random y postition overlap = false for j in 1 to i do --looping back to the objects already created ( = "MyBox_" + j as string OldPosX = execute ("$'" + +"'.pos.x") --get the x location of the previous OldPosY = execute ("$'" + +"'.pos.y") --get the y location of the previous diffX = abs(NewPosX - OldPosX) as integer diffY = abs(NewPosY - OldPosY) as integer if (diffX < tolerance and diffY< tolerance) do overlap = true --tolerance for overlaping ) if (overlap ==false) do --if there is no overlap ( b.pos = [NewPosX, NewPosY, 0] --move the box created in the new position ) sv = sv + 1 if sv>500 then break() -- after 500 tries break ) )
Old 03 March 2013   #6
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
Thread Closed share thread

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Society of Digital Artists

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump

All times are GMT. The time now is 10:42 PM.

Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.