CGTalk > Software Specific Forums > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 06-13-2013, 04:54 AM   #1
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
Creating Geometry from Planes

I am trying to write an importer that gets data where all the faces of geometry are defined only by three vertices, regardless of how many sides that face has. While it makes sense that an object can be defined this way as the objects are always presumed to be convex, it is a little baffling for me to actually figure out how to create the geometry.

Below is a simplified set of data that can be used to recreate a cube.

Code:
allPlanes = #() /*Add all the known points where each defines a plane: */ append allPlanes #([-64,64,64],[64,64,64],[64,-64,64]) append allPlanes #([-64,-64,-64],[64,-64,-64],[64,64,-64]) append allPlanes #([-64,64,64],[-64,-64,64],[-64,-64,-64]) append allPlanes #([64,64,-64],[64,-64,-64],[64,-64,64]) append allPlanes #([64,64,64],[-64,64,64],[-64,64,-64]) append allPlanes #([64,-64,-64],[-64,-64,-64],[-64,-64,64]) allPlanes.count /* How many faces in the resulting mesh */


If you were to create a plane for each item in the array, they would all intersect and the innermost section would be a cube. You could then select a face and, in this example, see that each has a fourth vertex. More complex geometry would have more verts added in faces .

Can anyone share some expertise on a way to convert this into a full working piece of geometry? The various methods I've come up just don't work... and the easiest cheat I've tried ( nvpx.CreateConvexFromPoints() ) always ends up with verts that are not exactly where I fed in the positions (always moving a tiny fraction off... but unusable because of this).
 
Old 06-13-2013, 02:22 PM   #2
Swordslayer
isKindOf Artist
 
Swordslayer's Avatar
portfolio
Vojtech Cada
3D generalist
Czech Republic
 
Join Date: Jun 2006
Posts: 330
Send a message via ICQ to Swordslayer
Well, this might be an overkill but did you try slicing the stuff? With a reasonably small number of planes it might be good enough:

Code:
( local allPlanes = #( #([-64,64,64],[64,64,64],[64,-64,64]), #([-64,-64,-64],[64,-64,-64],[64,64,-64]), #([-64,64,64],[-64,-64,64],[-64,-64,-64]), #([64,64,-64],[64,-64,-64],[64,-64,64]), #([64,64,64],[-64,64,64],[-64,64,-64]), #([64,-64,-64],[-64,-64,-64],[-64,-64,64])) local maxFloat = 3.4028e+038 local minFloat = -3.4028e+038 local totalMin = [maxFloat, maxFloat, maxFloat] local totalMax = [minFloat, minFloat, minFloat] local getVertPos = polyOp.getVert local slice = polyOp.slice local deleteVerts = polyOp.deleteVerts local cap = polyOp.capHolesByEdge fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) > 0 fn slicePoly obj pos vector = ( local verts = obj.verts as bitArray slice obj #all (ray pos vector) for vert in verts where NOT isPositiveDir (getVertPos obj vert) vector pos do verts[vert] = false deleteVerts obj verts cap obj #all ) for points in allPlanes do ( for pos in points do ( if pos.x < totalMin.x then totalMin.x = pos.x else if pos.x > totalMax.x do totalMax.x = pos.x if pos.y < totalMin.y then totalMin.y = pos.y else if pos.y > totalMax.y do totalMax.y = pos.y if pos.z < totalMin.z then totalMin.z = pos.z else if pos.z > totalMax.z do totalMax.z = pos.z ) ) local center = (totalMax + totalMin)/2 local dimensions = (totalMax - totalMin) * 2 local poly = convertToPoly (Box pivot:(center + [0, 0, dimensions.z/2]) width:dimensions.x length:dimensions.y height:dimensions.z pos:center) for points in allPlanes do ( local vector = normalize (cross (points[2] - points[1]) (points[3] - points[2])) if isPositiveDir center vector points[1] do vector *= -1 slicePoly poly points[1] vector ) )
__________________
Blog :: LinkedIn profile
 
Old 06-13-2013, 03:54 PM   #3
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
This is really helpful. The thought of slice was on my radar.

Your example works great for points around the origin... but if they are all offset somewhere then it fails.

For example, use these points:

Code:
allPlanes = #(#([185,-1685,0], [21,-1685,0], [21,-1942,0]), #([185,-1685,176], [185,-1942,176], [21,-1942,176]), #([185,-1942,176], [185,-1942,0], [21,-1942,0]), #([185,-1685,176], [185,-1685,0], [185,-1942,0]), #([21,-1685,176], [21,-1685,0], [185,-1685,0]), #([21,-1942,176], [21,-1942,0], [21,-1685,0]))


I thought maybe it was that the coordinate system was wrong at the time slice is called, hoping changing the slice() line to this would fix it:

Code:
in coordsys world ( slice obj #all (ray pos vector) node:obj )


But that does not help.

Any ideas?

Last edited by wallworm : 06-13-2013 at 04:07 PM. Reason: grammar error
 
Old 06-13-2013, 05:48 PM   #4
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
Fiddling some more... I wanted to try this:

Code:
in coordsys world ( slice obj #all (ray pos vector) node:obj for vert in verts where NOT isPositiveDir (getVertPos obj vert node:obj) vector pos do verts[vert] = false )


Whether this might help I don't know because there is always a MAXScript error:

Quote:
>> MAXScript Rollout Handler Exception:
-- Argument count error: slice wanted 3, got 6 <<



In this instance, slice() is an alias for polyOp.slice . According to the docs, polyOp.slice takes three manadatory parameters and one optional parameter (node so that you can designate a coordinate system. Whenever I try setting node: there is an exception.

Is this a bug in MAXScript (currently using 2014) or are the docs incorrect (it lists node: as a parameter in MXS docs for 2011 and 2014... didn't check others).
 
Old 06-13-2013, 06:12 PM   #5
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,160
Send a message via ICQ to denisT
Quote:
Originally Posted by wallworm
I am trying to write an importer that gets data where all the faces of geometry are defined only by three vertices, regardless of how many sides that face has. While it makes sense that an object can be defined this way as the objects are always presumed to be convex, it is a little baffling for me to actually figure out how to create the geometry.

in short, do you want to make a convex hull around a points cloud?
 
Old 06-13-2013, 06:30 PM   #6
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
Quote:
Originally Posted by denisT
in short, do you want to make a convex hull around a points cloud?


Yes, that is really the goal. The hull has to use the points provided. Like mentioned above, when I used the nvpx.CreateConvexFromPoints() method, it moves the verts ever so slightly; for example, if a point passed into it as [883,1323,177] will result in [883.004,1323.992,177.004], etc., which is not appropriate for my needs. I need the points to be precisely at the coordinates specified.
 
Old 06-13-2013, 07:10 PM   #7
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,160
Send a message via ICQ to denisT
Quote:
Originally Posted by wallworm
Yes, that is really the goal. The hull has to use the points provided. Like mentioned above, when I used the nvpx.CreateConvexFromPoints() method, it moves the verts ever so slightly; for example, if a point passed into it as [883,1323,177] will result in [883.004,1323.992,177.004], etc., which is not appropriate for my needs. I need the points to be precisely at the coordinates specified.

that's true. CreateConvexFromPoints and CreateConvexHull both have some inflation precision and there is no way to set it up for a perfect hull.
the only way that i see is to write your own Convex Hull making tool. Algorithms are know and can be easily found in the internet. MXS version of this tool probably will be slow for big meshes, but will work for sure.
 
Old 06-13-2013, 07:18 PM   #8
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
I think that Vojtech's solution works if the Box constructor doesn't include the pivot parameter! I need to test some more but I changed:


Code:
local poly = convertToPoly (Box pivot:(center + [0, 0, dimensions.z/2]) width:dimensions.x length:dimensions.y height:dimensions.z pos:center)


to

Code:
local poly = convertToPoly (Box width:dimensions.x length:dimensions.y height:dimensions.z pos:center)


and it seems to work.

I'll report back in a bit.
 
Old 06-14-2013, 08:14 AM   #9
Swordslayer
isKindOf Artist
 
Swordslayer's Avatar
portfolio
Vojtech Cada
3D generalist
Czech Republic
 
Join Date: Jun 2006
Posts: 330
Send a message via ICQ to Swordslayer
Yeah, sorry about that, the pivot part should have been

Code:
pivot:[0, 0, dimensions.z/2]


Or use some other primitive that already has a pivot in the center.
__________________
Blog :: LinkedIn profile
 
Old 06-14-2013, 11:55 PM   #10
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
Quote:
Originally Posted by Swordslayer
Yeah, sorry about that, the pivot part should have been

Code:
pivot:[0, 0, dimensions.z/2]


Or use some other primitive that already has a pivot in the center.


Vojtech ... do not apologize. I am very grateful. You saved me several hours of work learning those functions, and taught me how to use them in practice more quickly. I will share some credit in my docs when I've got the tool done.

Thank goodness for people like you, Denis and all the other guys in the Max dev community. You've all helped me learn or saved me time a million times! I personally think that the Max dev community is one of the coolest crowds in the world!
 
Old 10-02-2013, 01:19 PM   #11
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
I need to return to this thread because there is a problem related to this that I just can't figure out.

When using Vojtech's code, the functions work as expected 99.9% of the time. However, some of the objects that I'm creating are broken.

I've narrowed it down to the function isPositiveDir() from above

Code:
fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) > 0


When I changed it to this:

Code:
fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) >= 0


It now seems to work 99.99% (an extra smidgeon of correctness).

But there are still occasions where it is returning false when it should be true... and I cannot see any kind of differences between the giant majority that work and the very small percentage that just fail.

My guess is some kind of rounding error that makes position values go just slightly off... but if that is that case I don't know what I can do about that.

Any ideas?
 
Old 10-02-2013, 05:39 PM   #12
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
Below is a sample chunk of code edited to display the problem. It includes a set points that cause the functions to fail. I also modified it to add Point() objects at the locations where the object's vertices should have been had the function worked correctly:

Code:
( local allPlanes = #() append allPlanes #([5664,-368,328], [5264,-416,376], [5264,-576,376]) append allPlanes #([5664,-496,280], [5264,-576,232], [5264,-416,232]) append allPlanes #([5264,-416,376], [5264,-416,232], [5264,-576,232]) append allPlanes #([5664,-496,328], [5664,-496,280], [5664,-368,280]) append allPlanes #([5664,-368,328], [5664,-368,280], [5264,-416,232]) append allPlanes #([5664,-496,280], [5664,-496,328], [5264,-576,376]) local maxFloat = 3.4028e+038 local minFloat = -3.4028e+038 local totalMin = [maxFloat, maxFloat, maxFloat] local totalMax = [minFloat, minFloat, minFloat] local getVertPos = polyOp.getVert local slice = polyOp.slice local deleteVerts = polyOp.deleteVerts local cap = polyOp.capHolesByEdge fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) > 0 fn slicePoly obj pos vector = ( local verts = obj.verts as bitArray slice obj #all (ray pos vector) for vert in verts where NOT isPositiveDir (getVertPos obj vert) vector pos do verts[vert] = false deleteVerts obj verts cap obj #all ) for points in allPlanes do ( for pos in points do ( if pos.x < totalMin.x then totalMin.x = pos.x else if pos.x > totalMax.x do totalMax.x = pos.x if pos.y < totalMin.y then totalMin.y = pos.y else if pos.y > totalMax.y do totalMax.y = pos.y if pos.z < totalMin.z then totalMin.z = pos.z else if pos.z > totalMax.z do totalMax.z = pos.z Point pos:pos ) ) local center = (totalMax + totalMin)/2 local dimensions = (totalMax - totalMin) * 2 local poly = convertToPoly (Box pivot:(center + [0, 0, dimensions.z/2]) width:dimensions.x length:dimensions.y height:dimensions.z pos:center) for points in allPlanes do ( local vector = normalize (cross (points[2] - points[1]) (points[3] - points[2])) if isPositiveDir center vector points[1] do vector *= -1 slicePoly poly points[1] vector ) )


EDIT... oops typo in post earlier.

Last edited by wallworm : 10-02-2013 at 05:46 PM.
 
Old 10-15-2013, 08:44 PM   #13
wallworm
Shawn Olson
 
wallworm's Avatar
portfolio
Shawn Olson
Wall Worm
Columbus, USA
 
Join Date: Jul 2011
Posts: 205
So I found a fix to this problem... here is modified code for anyone having a similar problem. The problem was related again to where the pivot is in a Box when created.

Code:
( local allPlanes = #() append allPlanes #([5664,-368,328], [5264,-416,376], [5264,-576,376]) append allPlanes #([5664,-496,280], [5264,-576,232], [5264,-416,232]) append allPlanes #([5264,-416,376], [5264,-416,232], [5264,-576,232]) append allPlanes #([5664,-496,328], [5664,-496,280], [5664,-368,280]) append allPlanes #([5664,-368,328], [5664,-368,280], [5264,-416,232]) append allPlanes #([5664,-496,280], [5664,-496,328], [5264,-576,376]) local maxFloat = 3.4028e+038 local minFloat = -3.4028e+038 local totalMin = [maxFloat, maxFloat, maxFloat] local totalMax = [minFloat, minFloat, minFloat] local getVertPos = polyOp.getVert local slice = polyOp.slice local deleteVerts = polyOp.deleteVerts local cap = polyOp.capHolesByEdge fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) > 0 fn slicePoly obj pos vector = ( local verts = obj.verts as bitArray slice obj #all (ray pos vector) for vert in verts where NOT isPositiveDir (getVertPos obj vert) vector pos do verts[vert] = false deleteVerts obj verts cap obj #all ) for points in allPlanes do ( for pos in points do ( if pos.x < totalMin.x then totalMin.x = pos.x else if pos.x > totalMax.x do totalMax.x = pos.x if pos.y < totalMin.y then totalMin.y = pos.y else if pos.y > totalMax.y do totalMax.y = pos.y if pos.z < totalMin.z then totalMin.z = pos.z else if pos.z > totalMax.z do totalMax.z = pos.z Point pos:pos ) ) local center = (totalMax + totalMin)/ 2 local dimensions = (totalMax - totalMin) * 2 local poly = convertToPoly (Box width:dimensions.x length:dimensions.y height:(dimensions.z) pos:[( center.x),( center.y),( (totalMin.z ))] ) for points in allPlanes do ( local vector = normalize (cross (points[2] - points[1]) (points[3] - points[2])) if isPositiveDir center vector points[1] do vector *= -1 slicePoly poly points[1] vector ) )
 
Old 10-15-2013, 08:44 PM   #14
CGTalk Moderation
Lord of the posts
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,481
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


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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
CGSociety
Society of Digital Artists
www.cgsociety.org

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

All times are GMT. The time now is 01:53 AM.


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