Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JokerMartini/7d0b27ed4af4b8ff3b9c to your computer and use it in GitHub Desktop.
Save JokerMartini/7d0b27ed4af4b8ff3b9c to your computer and use it in GitHub Desktop.
Maxscript: Generates random points on a targeted surface. Credit Bobo.
fn GenerateRandomPointsOnSurface theObj PointCount useIntersection:true numAttempts:10 =
(
delete $Teapot* --delete previous teapots (remove if you are not making teapots)
local st = timestamp() --get the start time
seed 12345 --set the random seed to a static number to get the same distribution each run
local theMesh = snapshotasMesh theObj --snapshot the TriMesh of the object
local theCount = theMesh.numfaces --get the number of faces in the TriMesh
local theNewObjectsArray = #() --init. an array for the objects to create
local theArea = 0 --init. a variable to hold the count.
for f = 1 to theCount do theArea += meshop.getFaceArea theMesh f --collect the area of the mesh
local ObjectsPerArea = PointCount / theArea --calculate the objects per square unit
local theIndices = for f = 1 to theCount collect f --collect the indices of the faces
local theRandomIndices = #() --init. an array to collect them randomly
while theIndices.count > 0 do --repeat until there are no indices left
(
theIndex = random 1 theIndices.count --pick a random face from the list
append theRandomIndices theIndices[theIndex] --add to the random list
deleteItem theIndices theIndex --and delete from the original list
)
local cnt = 0 --initialize a counter of the created points
for f in theRandomIndices while cnt < PointCount do --loop through the random faces until the count is reached
(
local theFace = getFace theMesh f --get the face def. of the random face
local theFactor = ceil ((meshop.getFaceArea theMesh f)*ObjectsPerArea) --calculate the points for the face, at least one.
local theVert1 = (getVert theMesh theFace.x) --get the first vertex' position
local theVert2 = (getVert theMesh theFace.y) --get the second vertex' position
local theVert3 = (getVert theMesh theFace.z) --get the third vertex' position
for i = 1 to theFactor while cnt < PointCount do --loop from 1 to the number of points on the face
(
local theNewObj = teapot radius:(random 2.0 5.0) wirecolor:red --create a teapot with random radius
theNewObj.transform = matrixFromNormal (getFaceNormal theMesh f) --set TM based on normal
local positionNotValid = true --raise a flag that the position is not valid yet
for attempts = 1 to numAttempts while positionNotValid do --repeat until position is valid or max. attempts have been made
(
local theX = random 0.0 1.0 --get a random X
local theY = random 0.0 1.0 --get a random Y
if theX+theY > 1.0 do --if the sum is greater than 1, subtract them from 1.0
(
theX = 1.0 - theX
theY = 1.0 - theY
)
local theZ = 1.0 - theX - theY --the third bary coord is 1.0 minus the other two
theNewObj.pos = (theVert1*theX + theVert2*theY + theVert3*theZ) --set position using barycentric coords.
--if no intersection is requested, or if there is no intersection with existing objects,
if not useIntersection or (for o in theNewObjectsArray where intersects theNewObj o collect o).count == 0 do
(
append theNewObjectsArray theNewObj --add the new object to the array
cnt += 1 --increase the index
positionNotValid = false --lower the flag to stop iterating
)
)--end attempts loop
if positionNotValid do delete theNewObj --if all attempts failed due to intersections, delete the object
)--end i loop
)--end f loop
delete theMesh --free the memory from the TriMesh
format "Time: % ms\n" (timestamp()-st) --report the time
cnt --returns number of created objects
)
GenerateRandomPointsOnSurface $Plane001 1000 useIntersection:true numAttempts:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment