Build a polygonal description for an existing object

Discussions about SOFTIMAGEs© Interactive Creative Environment©
Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 10:39

For my building generator it would be very useful if it had a way to generate certain objects, such as a premodeled cornice. I don't want to have to link the ICE tree to another object in the scene. The ICE tree should be able to generate an object without external input.

All you'd need for this to happen is the polygonal description of the object. You would supply it via a String to array and rebuild the object directly in the ICE tree. But what's a good way to do this? I've exported a test object into an OBJ and copied all vertex data from that OBJ into a String to Array. This works great. But building polygons in the right vertex order seems difficult.

The example OBJ has these vertices:

Code: Select all

#begin 14 vertices
v -4.000000 0.543223 -4.000000
v -4.000000 0.543223 4.000000
v -2.666667 0.000000 -4.000000
v -2.666667 0.000000 4.000000
v -1.333333 -0.212357 -4.000000
v -1.333333 -0.212357 4.000000
v -0.000000 -0.243325 -4.000000
v -0.000000 -0.243325 4.000000
v 1.333333 0.335440 -4.000000
v 1.333333 0.335440 4.000000
v 2.666667 0.550321 -4.000000
v 2.666667 0.550321 4.000000
v 4.000000 0.000000 -4.000000
v 4.000000 0.000000 4.000000
#end 14 vertices
And these polygons:

Code: Select all

#begin 6 faces
f 1//1 2//2 4//3 3//4 
f 3//5 4//6 6//7 5//8 
f 5//9 6//10 8//11 7//12 
f 7//13 8//14 10//15 9//16 
f 9//17 10//18 12//19 11//20 
f 11//21 12//22 14//23 13//24 
#end 6 faces
If you remove all "v " and replace all " " by "," you should get vertex data that works with the String to Array node.
But how would you interpret the polygon data?

Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Re: Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 11:45

Okay, the polygon data is always the first of the two numbers minus 1.

So this line:

Code: Select all

f 1//1 2//2 4//3 3//4
Becomes:
0,1,3,2,-2

This works excellently, and I can actually rebuild the object in ICE. The full polygon description for my sample object is:
1,2,4,3,-1,3,4,6,5,-1,5,6,8,7,-1,7,8,10,9,-1,9,10,12,11,-1,11,12,14,13,-1 (and subtract 1 from the resulting array)

Two problems:
a) Is there a way to automate this somehow? I ended up typing the polygon string by hand which would be cumbersome for detailed objects:
b) If I plug this data into a Create Topo node, it completely overwrites all existing topology with the new topology. An Add Polygon does not overwrit existing topology but can only take one polygon as input and would have to be looped I think?

Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Re: Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 11:51

Here is a compound that builds the test object using the data I copied from the .OJB. If you plug this compound into the ICE tree of say a cube, the cube will vanish and be replaced by the new topology. That's problem b) as described above.
You do not have the required permissions to view the files attached to this post.

User avatar
origin
Posts: 619
Joined: 09 Jun 2009, 09:59
Location: warsaw

Re: Build a polygonal description for an existing object

Post by origin » 10 Jun 2011, 11:55

as for b), use Merge Topo node

Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Re: Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 12:02

Thanks origin. Works great!
Now if I could automate the .OBJ extraction somehow, that would be great. Maybe there is a format better suited or something? It doesn't even have to be fully automated. Using a text editor with find and replace is fine. But that only works for the vertex data I think.

User avatar
Daniel Brassard
Posts: 878
Joined: 18 Mar 2010, 22:38
Location: St. Thomas, Ontario

Re: Build a polygonal description for an existing object

Post by Daniel Brassard » 10 Jun 2011, 12:10

For the benefit of others, the Wavefront OBJ format is defined as follows:

(from WIKIPEDIA)
Vertex

A valid vertex index starts from 1 and matches the corresponding vertex elements of a previously defined vertex list. Each face can contain more than three elements.

f v1 v2 v3 v4 ...

Vertex/texture-coordinate

Optionally, texture coordinate indices can be used to specify texture coordinates when defining a face. To add a texture coordinate index to a vertex index when defining a face, one must put a slash immediately after the vertex index and then put the texture coordinate index. No spaces are permitted before or after the slash. A valid texture coordinate index starts from 1 and matches the corresponding element in the previously defined list of texture coordinates. Each face can contain more than three elements.

f v1/vt1 v2/vt2 v3/vt3 ...

Vertex/texture-coordinate/normal

Optionally, normal indices can be used to specify normal vectors for vertices when defining a face. To add a normal index to a vertex index when defining a face, one must put a second slash after the texture coordinate index and then put the normal index. A valid normal index starts from 1 and matches the corresponding element in the previously defined list of normals. Each face can contain more than three elements.

f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...

Vertex/normal

As texture coordinates are optional, one can define geometry without them, but one must put two slashes after the vertex index before putting the normal index.

f v1//vn1 v2//vn2 v3//vn3 ...

so in Chris example f 1//1 2//2 4//3 3//4

would be read by the Wavefront OBJ exporter / parser

face vertex 1,2,4,3
face normal 1,2,3,4

as Softimage is 0 index based, substract 1 to the face vertex order to get Chris face vertex ordering f 0,1,3,2 and add -2 at the end to close the polygon definition.
$ifndef "Softimage"
set "Softimage" "true"
$endif

Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Re: Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 12:43

Okay, so I've been able to make things a bit easier with the Find/Replace option in Notepad++. It can use expressions, so replacing this:
//\d\d
with this:
,

turns this:
9//17 10//18 12//19 11//20
into this:
9,10,12,11,

It does not look like it can remove carriage returns because the search happens line per line. So every carriage return will have to be removed by hand (the String to Array stops pasting clipboard text when it hits a carriage return).

User avatar
origin
Posts: 619
Joined: 09 Jun 2009, 09:59
Location: warsaw

Re: Build a polygonal description for an existing object

Post by origin » 10 Jun 2011, 14:20

I think I can create script that reads obj files.
Meanwhile, select some poly mesh(es) and run this script.
It will create stringToArray nodes on object 'polymsh' containing data for createTopo node. If there is no polymsh object and it doesn't have icetree, script will create one.
It also prints vertex positions and poly description in console so If you don't wanna ice nodes creation, set createIcetree variable to 0.

Code: Select all

from win32com.client import constants as c

# script will look for object "polymsh" (or create one if there is no polymsh in scene)
# and will add there two stringtoArray nodes containing poly data of selected object(s)

createIcetree = 1
createComments = 1
whereToAddStringNodes = "polymsh"

x = Application
sel = x.Selection
true = 1
false = 0
null = ""

def createICEpolymsh(object,vertPos,polyDesc, comments, commentAdditionalString):
	oIcetrees = XSIFactory.CreateObject( "XSI.Collection" );
	oIcetrees = object.ActivePrimitive.ICETrees
	#check if there is icetree 'ICEtree' on object stack
	if oIcetrees.Count == 0:
		t = x.ApplyOp("ICETree", object.FullName, c.siNode)
		oIceOp=t	
	else:
		#if there is not, create one
		for oIcetree in oIcetrees:
			if oIcetree.Name =="ICETree":
				oIceOp = oIcetree
	#add stringtoarray nodes
	stringArray = x.AddICENode("StringToArray",oIceOp)
	stringArray2 = x.AddICENode("StringToArray",oIceOp)
	stringArray.Value_string = vertPos
	stringArray2.Value_string = polyDesc
	#create comments if necessary
	if comments == true:
		strArrayCmt = x.CreateICENodeComment(stringArray.FullName)
		strArrayCmt.Text = commentAdditionalString +" Vertex positions" 
		strArrayCmt = x.CreateICENodeComment(stringArray2.FullName)
		strArrayCmt.Text = commentAdditionalString + " Polygon description"

selTxt = sel.GetAsText()
if createIcetree == 1:
		obj = x.ActiveSceneRoot.FindChildren(whereToAddStringNodes, c.siPolyMeshType)
		if obj.Count == 0:
			opolymsh = x.GetPrim("EmptyPolygonMesh", "", "", "") #create empty polymsh if there is no whereToAddStringNodes named object in scene
		else:
			opolymsh = obj(0)
x.Selection.SetAsText(selTxt)
sel = x.Selection
for o in sel: #for every object in selection
	if o.Type != "polymsh":		#not polymesh
		print "Object "+ o.FullName +" is not polymesh"
		continue
	
	oGeo = o.ActivePrimitive.Geometry
	objFacets = oGeo.Polygons
	objPoints = oGeo.Points
	svertPos = ""
	spolyDescription = ""
	print "Object "+ o.FullName +" has " + str(oGeo.Points.Count) + " points and " + str(objFacets.Count) + " faces."
	#build vertex position string
	for v in objPoints:
		svertPos += str(v.Position.X)+","+str(v.Position.Y)+","+str(v.Position.Z)+","
	#build poly description string
	for face in objFacets:
		vert = face.Vertices
		for v in vert:
			spolyDescription += str(v.Index)+","
		spolyDescription+="-2," 	#negative value ends single poly desc
	#** print out values **
	print "Vertex positions:"
	print svertPos
	print "Polygon description:"
	print spolyDescription
	if createIcetree == 1:
		createICEpolymsh(opolymsh, svertPos, spolyDescription,createComments, o.FullName)

Chris_TC
Posts: 411
Joined: 22 Mar 2010, 16:43

Re: Build a polygonal description for an existing object

Post by Chris_TC » 10 Jun 2011, 15:03

Wooooooooow, that is mighty awesome of you. Thank you! :ymhug: :ymhug:
The script works great and makes this whole process much more convenient.