PDA

View Full Version : mesh intersection = deletion


JokerMartini
01-21-2012, 10:41 PM
I'm sure this question has been asked before.
I simply just want to take a select of objects and run a script which would delete them based on whether or not they test true for colliding meshes (*not bounding boxes)

Example:Image
delete all blue boxes which intersect with ring.
http://forums.cgsociety.org/attachment.php?attachmentid=166127&stc=1

Kickflipkid687
01-21-2012, 10:44 PM
Maybe do IntersectRayEX I believe, from each box upwards, and see if it hits any nodes (donut) and if it does, delete it.

JokerMartini
01-21-2012, 11:12 PM
This partially works but I'm not sure if it is the best way to go about doing so?
Thoughts everyone?


fn find_intersection z_node node_to_z =
(
local testRay = ray node_to_z.pos [0,0,-1]
local nodeMaxZ = z_node.max.z
testRay.pos.z = nodeMaxZ + 0.0001 * abs nodeMaxZ
intersectRay z_node testRay
)

for i in selection do
(
int_point = find_intersection $Circle001 i
if int_point != undefined then i.wirecolor = blue
)--end i loop

Kickflipkid687
01-21-2012, 11:18 PM
Yeah, I mixed it up, was thinking of intersectScene, but ya, your method works well.

I'm not sure how else you'd do it? Your method seems clean and fast.

JokerMartini
01-21-2012, 11:29 PM
Well It says the z direction right now.
I was wondering if it checks an object in all directions because it seems to be missing some object right now when i run it.


It surprisingly runs fast than i expected it to.

denisT
01-21-2012, 11:31 PM
Yeah, I mixed it up, was thinking of intersectScene, but ya, your method works well.

I'm not sure how else you'd do it? Your method seems clean and fast.

is the VolumeSelect modifier too boring?

Kickflipkid687
01-21-2012, 11:36 PM
Didn't know about that.

JokerMartini
01-22-2012, 01:29 AM
So is that the best way to test this scenario?

It seems to miss objects when i test it?

denisT
01-22-2012, 01:47 AM
This partially works but I'm not sure if it is the best way to go about doing so?
Thoughts everyone?


fn find_intersection z_node node_to_z =
(
local testRay = ray node_to_z.pos [0,0,-1]
local nodeMaxZ = z_node.max.z
testRay.pos.z = nodeMaxZ + 0.0001 * abs nodeMaxZ
intersectRay z_node testRay
)

for i in selection do
(
int_point = find_intersection $Circle001 i
if int_point != undefined then i.wirecolor = blue
)--end i loop


it might be a solution for only very specific cases. in real life the geometry intersection is very complicated thing. to make the calculation faster real-time engines use some tricks, i.e. get intersection bbox with bbox, bound primitive (box, sphere, cylinder, capsule) with a primitive, convex hulls intersection...
so this kind of task has to be simplified for getting enough accuracy.
if you need true intersection one of most popular technique is voxel (grid) method. to get progressive accuracy some techniques use the octree methods. there are some good octree c# free libraries in internet. try to find...

JokerMartini
01-22-2012, 06:54 AM
Where could I find examplea to do so using bouding primitive it convex hulls. Is like to stick within maxscriot and not expand to c# for the time being thanks though for letting me know as that being an option.

Panayot
01-22-2012, 11:11 AM
So is that the best way to test this scenario?

It seems to miss objects when i test it?
I have a feeling that you are looking for a method that is fast and accurate at the same time, if so you chasing a ghost.

JokerMartini
01-22-2012, 03:13 PM
Is doing a convex hull type of calculation something that would be a little more accurate and better?

Kickflipkid687
01-22-2012, 03:37 PM
My recent Shrink Wrap script I made can do convex hulls in a sense, which I didn't plan in the first place.

You could do the same, which wouldn't be necessarily 100% accurate, but is fast and should work for what u want. I just use MeshProjIntersect() for something like on your donut, and take a geosphere, and for each vert in the geo sphere, get the closest hit pos on the donut to make ur convex hull.

Then from there just do raycast like before at the convex hull?

denisT
01-22-2012, 04:05 PM
You could do the same, which wouldn't be necessarily 100% accurate, but is fast and should work for what u want. I just use MeshProjIntersect() for something like on your donut, and take a geosphere, and for each vert in the geo sphere, get the closest hit pos on the donut to make ur convex hull.

this method can't guaranty that the projected object will be convex.

JokerMartini
01-22-2012, 06:26 PM
It's ok if it is a little rough. That sounds a possible solution or something to build off of.
Would there be a possible way to do primitive based calculations. Like box or sphere ? Like bounding box. Unless there is a convex solution.

Kickflipkid687
01-22-2012, 06:39 PM
this method can't guaranty that the projected object will be convex.

Yeah, I know. But for his test, it might be ok.

JokerMartini
01-22-2012, 10:54 PM
I'm not sure if i see the benefit of doing the convex hull process that your mentioning verses what I'm doing right now

JokerMartini
01-22-2012, 11:14 PM
I messed with the voxel grid stuff.
I'm not getting any results from the hits?
I feel like this could possibly resolve what I'm after.


(
theSphere = selection as array
theGeoSphere = $Tube001
theObjectsHit = #() --init. an arrawy to collect face selection

rm = RayMeshGridIntersect () --create an instance of the Reference Target
rm.Initialize 1 --init. the voxel grid size to 10x10x10
rm.addNode theSphere --add the sphere to the grid
rm.buildGrid () --build the grid data (collecting faces into the grid voxels)
theGSMesh = snapshotasmesh theGeoSphere --grab the TriMesh of the Geosphere
for v = 1 to theGSMesh.numverts do --go through all verts of the Geosphere
(
thePos = getVert theGSMesh v --get the position of the vertex
theNormal = -(getNormal theGSMesh v) --get the normal of the vertex, reverse direction
theHitsCount = rm.intersectRay thePos theNormal false --intersect the ray with the sphere
if theHitsCount > 0 then --if have hit anything...
(
theIndex = rm.getClosestHit () --get the index of the closest hit by the ray
theFace = rm.getHitFace theIndex --get the face index corresponding to that indexed hit
append theObjectsHit theFace --add to the face array to select the face...
)
else
format "The Ray % Missed\n" v
)
for obj in theObjectsHit do obj.wirecolor = blue
)

Kickflipkid687
01-22-2012, 11:37 PM
Both RayMeshGridIntersect and MeshProjIntersect only accept 1 mesh to build the voxel grid.

It looks like your trying to do the opposite, add the objects to hit as an array into it?
That's why I was saying, ud want to either convert your torus to a Mesh or collapse other objects as snapshots into 1 mesh and put that into the voxel grid. It has to be a mesh that goes in.

So if you snapshotted ur Torus, put that in, set Gridsize to like 25 and built, then for each box pos , do the closestHit check in MeshProjIntersect to get the hit or not on the Torus, and if so, collect the box.

Kickflipkid687
01-22-2012, 11:41 PM
This is a function I setup to call for each vert pos in a mesh, using a global built MeshProjIntersect setup.


--GET Closest Hit
fn tTclosestPointOnSurf surf refPos =
(
tTShrinkHitTest.closestFace refPos doubleSided:true
closestPoint = tTShrinkHitTest.getHitPos()
closestFace = tTShrinkHitTest.GetHitFace()

return #(closestPoint,closestFace)
)

JokerMartini
01-24-2012, 02:06 PM
I've attached the script and file that I'm testing on.
It is registering objects that are not getting hit by the tube as "getting hit" resulting in changing their wirecolor to blue. What would be a solution to this? The voxel processing method?

My other thought, which would not be ideal in anyway would be to snapshot the mesh and break every polygon into a separate object and then skinwrap it to the original mesh and then do a bounding box collision test for each object in the scene versus each object that represented the tube.



http://forums.cgsociety.org/attachment.php?attachmentid=166161&stc=1


fn find_intersection z_node node_to_z =
(
local testRay = ray node_to_z.pos [0,0,-1]
local nodeMaxZ = z_node.max.z
testRay.pos.z = nodeMaxZ + 0.0001 * abs nodeMaxZ
intersectRay z_node testRay
)

for t = 1 to 20 do
(
slidertime = t

for i in selection do
(
int_point = find_intersection $Tube001 i
if int_point != undefined then i.wirecolor = blue
)--end i loop

)

denisT
01-24-2012, 03:24 PM
is the VolumeSelect modifier too boring?


with redraw off with undo off
(
delete objects
gc()

xcount = 24
ycount = 24
inipos = [0,0,0]
boxsize = 10.
spacing = 2.
nodes = #()

setCommandPanelTaskMode mode:#create
-- create scene:
-- create boxes:
for y=0 to ycount-1 do
(
for x=0 to xcount-1 do
(
b = box name:(formattedprint (y*xcount + x + 1) format:"04d") \
width:boxsize length:boxsize height:boxsize \
pos:(inipos + [x*(boxsize+spacing), y*(boxsize+spacing), 0]) \
wirecolor:yellow
append nodes b
)
)
-- create selection mesh:
rad = xcount*(boxsize + spacing)*0.4
selnode = Torus name:"sel_node" segs:24 sides:12 radius1:rad radius2:(0.7*boxsize) mapcoords:off \
pos:(inipos + [rad, rad, boxsize/2]*1.1) wirecolor:green

-- add volume select mofifier:
vsel = VolumeSelect volume:3 level:2 type:1
vsel.node = selnode

disablerefmsgs()
t1 = timestamp()
addmodifier nodes vsel

-- collect selected/intersected nodes:
selected = for n in nodes where n.mesh.selectedfaces.count > 0 collect n

-- delete modifier:
deletemodifier nodes vsel

selected.wirecolor = red

t2 = timestamp()
enablerefmsgs()
format ">> time:%\n" (t2-t1)
format "\tnodes:% selected:%\n" nodes.count selected.count
)

it was not boring for me...

JokerMartini
01-24-2012, 04:38 PM
Such a clever idea. That works out great. It is exactly what I was after. I will mess around with it today and see what result I get and if it works in the long run of things for what my main goal is.

I didn't know vol select could work like that.
Very cool.

JokerMartini
01-31-2012, 07:45 PM
Obviously this method isn't the fastest method inside of max as of right now.

If one is to use a gizmo how do I then detect collision? Is it using the same method?

JokerMartini
07-05-2012, 03:51 PM
Could someone test this out and let me know what I'm missing.
For some reason it thinks the cubes within the middle of the torus are being selected by the mesh when in reality they are not intersecting it at all.
But as a result of this it is testing true when it shouldn't be.

Just take the below script and run it. You'll notice right away what is going wrong.


(
--//add key z
fn fnAnimate obj atTime =
(
obj.position.controller.Z_Position.controller = bezier_float ()
sKey = addNewKey obj.position.controller.Z_Position.controller atTime
endKey = addNewKey obj.position.controller.Z_Position.controller (atTime+3f)
endKey.value -= 40.0
)


with redraw off with undo off
(
delete objects
gc()

xcount = 24
ycount = 24
inipos = [0,0,0]
boxsize = 10.
spacing = 2.
nodes = #()

setCommandPanelTaskMode mode:#create
-- create boxes:
for y=0 to ycount-1 do
(
for x=0 to xcount-1 do
(
b = box name:(formattedprint (y*xcount + x + 1) format:"04d") \
width:boxsize length:boxsize height:boxsize \
pos:(inipos + [x*(boxsize+spacing), y*(boxsize+spacing), 0]) \
wirecolor:yellow
append nodes b
)
)

subSample = 1 --subsample for fast moving objects

-- create selection mesh:
_objArr = nodes
_hitNodes = #()
collisionObj = Torus name:"sel_node" segs:24 sides:24 radius1:80 radius2:20 mapcoords:on pos:[150,-100,0] wirecolor:green
in coordsys local rotate collisionObj (EulerAngles 90 0 0)
with animate on (at time 30 (collisionObj.pos = [150,350,0]))

-- add volume select mofifier:
vsel = VolumeSelect level:1 type:1 method:0 volume:3 node:collisionObj --//Add volume select for "mesh intersection" testing

disablerefmsgs()
t1 = timestamp()

for t in animationrange.start to animationrange.end by subSample do --Go frame by frame and find the objects colliding with the actual mesh of the collisionObj, but only one time per object)
(
at time t
(
local _tmpArr = for obj in _objArr where (intersects collisionObj obj) collect obj
addmodifier _tmpArr vSel
for obj in _tmpArr where obj.mesh.selectedVerts.count > 0 do
(
append _hitNodes #(obj,t)
idx = findItem _objArr obj
if idx != 0 do deleteItem _objArr idx
)
deletemodifier _tmpArr vSel --// Delete VS modifier:
)
)

t2 = timestamp()
enablerefmsgs()
format ">> time:%\n" (t2-t1)
)

for o in _hitNodes do
(
obj = o[1]
theTime = o[2]
obj.wirecolor = red
fnAnimate obj theTime
)

)

CGTalk Moderation
07-05-2012, 03:51 PM
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.