Become a member of the CGSociety

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

Thread Tools Display Modes
  02 February 2013

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
  02 February 2013
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
 	local rendParticles=renderParticles()
 	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
 	evt.appendAction birthAction 
 	evt.appendAction positionObjectAction 
 	evt.appendAction speedBySurfaceAction 
 	evt.appendAction rotationAction 
 	evt.appendAction speedAction 
 	pf.appendInitialActionList evt
 	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
  02 February 2013
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.
  02 February 2013
ok thanks I will try.
  03 March 2013
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
  03 March 2013
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.
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
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 09:55 AM.

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