# Creating Geometry from Planes

 Thread Tools Search this Thread Display Modes
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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. `````` 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). __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 06 June 2013 Swordslayer isKindOf Artist   portfolio Vojtech Cada 3D generalist Czech Republic 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: ``````( 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 ) )`````` __________________ Scripts :: linkedin share quote
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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: `````` 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: `````` in coordsys world ( slice obj #all (ray pos vector) node:obj ) `````` But that does not help. Any ideas? __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin Last edited by wallworm : 06 June 2013 at 04:07 PM. Reason: grammar error share quote
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA Fiddling some more... I wanted to try this: `````` 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). __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 06 June 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA 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? share quote
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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. __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 06 June 2013 denisT MAX Doctor   portfolio Denis Trofimov CA, USA 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. share quote
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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: ``````local poly = convertToPoly (Box pivot:(center + [0, 0, dimensions.z/2]) width:dimensions.x length:dimensions.y height:dimensions.z pos:center)`````` to ``````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. __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 06 June 2013 Swordslayer isKindOf Artist   portfolio Vojtech Cada 3D generalist Czech Republic Yeah, sorry about that, the pivot part should have been ``pivot:[0, 0, dimensions.z/2]`` Or use some other primitive that already has a pivot in the center. __________________ Scripts :: linkedin share quote
 06 June 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA Originally Posted by Swordslayer: Yeah, sorry about that, the pivot part should have been ``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! __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 10 October 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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 `````` fn isPositiveDir pos vector vectorPos = dot vector (pos - vectorPos) > 0`````` When I changed it to this: `````` 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? __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 10 October 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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: `````` ( 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. __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin Last edited by wallworm : 10 October 2013 at 05:46 PM. share quote
 10 October 2013 wallworm Shawn Olson   portfolio Shawn Olson Wall Worm Columbus, USA 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. `````` ( 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 ) ) `````` __________________ Shawn Olson Autodesk Expert Elite 3ds Max Charter Member Developer of: Wall Worm Tools for the Source Game Engine CorVex Level Design Plugin share quote
 10 October 2013 CGTalk Moderation Expert 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. share quote

 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 vBulletinCopyright ©2000 - 2006, Jelsoft Enterprises Ltd.