User Tools

Site Tools


Geometry Triangulate

Summary

Below is an example demonstrating the use of the geometry pipeline to convert geometry constructed of quadrilaterals into geometry constructed of adjacent triangles (both visually and in order of facet indices).

See Also: Geometry Detriangulate

API Areas of Interest

Example

Geometry_Triangulate.dsa
// Define an anonymous function;
// serves as our main loop,
// limits the scope of variables
(function(){
 
	// Initialize 'static' variables that hold modifier key state
	var s_bShiftPressed = false;
	var s_bControlPressed = false;
	var s_bAltPressed = false;
	var s_bMetaPressed = false;
 
	// If the "Action" global transient is defined, and its the correct type
	if( typeof( Action ) != "undefined" && Action.inherits( "DzScriptAction" ) ){
		// If the current key sequence for the action is not pressed
		if( !App.isKeySequenceDown( Action.shortcut ) ){
			updateModifierKeyState();
		}
	// If the "Action" global transient is not defined
	} else if( typeof( Action ) == "undefined" ) {
		updateModifierKeyState();
	}
 
	/*********************************************************************/
	// void : A function for updating the keyboard modifier state
	function updateModifierKeyState()
	{
		// Get the current modifier key state
		var nModifierState = App.modifierKeyState();
		// Update variables that hold modifier key state
		s_bShiftPressed = (nModifierState & 0x02000000) != 0;
		s_bControlPressed = (nModifierState & 0x04000000) != 0;
		s_bAltPressed = (nModifierState & 0x08000000) != 0;
		s_bMetaPressed = (nModifierState & 0x10000000) != 0;
	};
 
	/*********************************************************************/
	// void : A function for printing only if debugging
	function debug()
	{
		// If we are not debugging
		if( !s_bAltPressed ){
			// We are done...
			return;
		}
 
		// Convert the arguments object into an array
		var aArguments = [].slice.call( arguments );
 
		// Print the array
		print( aArguments.join(" ") );
	};
 
	/*********************************************************************/
	// Boolean : A function for testing whether or not a QObject instance
	// inherits one of a list of types
	function inheritsType( oObject, aTypeNames )
	{
		// If the object does not define the 'inherits' function
		if( !oObject || typeof( oObject.inherits ) != "function" ){
			// We are done... it is not a QObject
			return false;
		}
 
		// Iterate over the list of type names
		for( var i = 0, nTypes = aTypeNames.length; i < nTypes; i += 1 ){
			// If the object does not inherit the 'current' type
			if( !oObject.inherits( aTypeNames[i] ) ){
				// Next!!
				continue;
			}
 
			// Return the result
			return true;
		}
 
		// Return the result
		return false;
	};
 
	/*********************************************************************/
	// DzNode : A function for getting the root of a node
	function getRootNode( oNode )
	{
		// If we have a node and it is a bone
		if( oNode && inheritsType( oNode, ["DzBone"] ) ){
			// We want the skeleton
			return oNode.getSkeleton();
		}
 
		// Return the original node
		return oNode;
	};
 
	/*********************************************************************/
	// DzObject : A function for getting the object for a node
	function getObjectForNode( oNode, bRoot )
	{
		// Get the node
		var oContextNode = bRoot ? getRootNode( oNode ) : oNode;
		// If we do not have a root node
		if( !oContextNode ){
			// We are done...
			return null;
		}
 
		// Get the object of the root node
		var oObject = oContextNode.getObject();
		// If we do not have an object
		if( !oObject ){
			// We are done...
			return null;
		}
 
		// Return the object
		return oObject;
	};
 
	/*********************************************************************/
	// DzShape : A function for getting the shape for a node
	function getShapeForNode( oNode, bRoot )
	{
		// Get the object of the node
		var oObject = getObjectForNode( oNode, bRoot );
		// If we do not have an object
		if( !oObject ){
			// We are done...
			return null;
		}
 
		// Get the shape of the root node
		var oShape = oObject.getCurrentShape();
		// If we do not have a shape
		if( !oShape ){
			// We are done...
			return null;
		}
 
		// Return the shape
		return oShape;
	};
 
	/*********************************************************************/
	// DzGeometry : A function for getting the geometry for the root of a node
	function getGeometryForNode( oNode, bRoot, bCached )
	{
		// Get the shape of the root node
		var oShape = getShapeForNode( oNode, bRoot );
		// If we do not have a shape
		if( !oShape ){
			// We are done...
			return null;
		}
 
		// If we are getting the cached geometry
		if( bCached ){
			// Update the working mesh
			//oShape.invalidateWorkingMesh();
 
			// Get the object of the root node
			var oObject = getObjectForNode( oNode, bRoot );
 
			// Return the geometry
			return oObject.getCachedGeom();
		}
 
		// Get the geometry of the root node
		var oGeometry = oShape.getGeometry();
		// If we do not have a geometry
		if( !oGeometry ){
			// We are done...
			return null;
		}
 
		// Return the geometry
		return oGeometry;
	};
 
	/*********************************************************************/
	// DzFacetMesh : A function for getting the facet mesh for a node
	function getFacetMeshForNode( oNode, bRoot, bCached )
	{
		// Get the geometry of the node
		var oGeometry = getGeometryForNode( oNode, bRoot, bCached );
		// If we do not have a facet mesh
		if( !inheritsType( oGeometry, ["DzFacetMesh"] ) ){
			// We are done...
			return null;
		}
 
		// Return the geometry
		return oGeometry;
	};
 
	/*********************************************************************/
	// Array : A function for weeding out non-unique elements of an array
	function unique( vValue, nIndex, aArray ) { 
		//
		return aArray.indexOf( vValue ) === nIndex;
	};
 
	/*********************************************************************/
	// Get the primary selection
	var oNode = getRootNode( Scene.getPrimarySelection() );
	// If nothing is selected
	if( !oNode ){
		// We are done...
		return;
	}
 
	// Get the mesh of the root node
	var oMesh = getFacetMeshForNode( oNode, true, false );
	// If we do not have a mesh
	if( !oMesh ){
		// We are done...
		return;
	}
 
	// Get the number of facets in the mesh
	var nFacets = oMesh.getNumFacets();
 
	// Decalre working variable
	var oFaceGroup;
 
	// Get the number of face groups
	var nFaceGroups = oMesh.getNumFaceGroups();
 
	// Pre-size the array of face group names
	var aFaceGroups = new Array( nFaceGroups );
 
	// Iterate over the face groups
	for( var i = 0; i < nFaceGroups; i += 1 ){
		// Get the 'current' face group
		oFaceGroup = oMesh.getFaceGroup( i );
 
		// Capture the face group name
		aFaceGroups[ i ] = oFaceGroup.name;
	}
 
	// Decalre working variable
	var oSurface;
 
	// Get the number of surfaces
	var nSurfaces = oMesh.getNumMaterialGroups();
 
	// Pre-size the array of surface names
	var aSurfaceNames = new Array( nSurfaces );
 
	// Iterate over the surfaces
	for( var i = 0; i < nSurfaces; i += 1 ){
		// Get the 'current' surface
		oSurface = oMesh.getMaterialGroup( i );
 
		// Capture the surface name
		aSurfaceNames[ i ] = oSurface.name;
	}
 
	// Decalre working variables
	var oFacet;
	var aVertsA, aVertsB;
	var aUVsA, aUVsB;
 
	// Initialize the facet data index
	var nFacetDataIdx = 0;
 
	// Pre-size the array of facet data objects
	var aFacetDatas = new Array( nFacets * 2 );
 
	// Iterate over all the facets
	for( var i = 0; i < nFacets; i += 1 ){
		// Get the 'current' facet
		oFacet = oMesh.getFacet( i );
 
		// Get the vertex indices for the first triangle
		aVertsA = [ oFacet.vertIdx1, oFacet.vertIdx2, oFacet.vertIdx3 ];
		// Get the UV indices for the first triangle
		aUVsA = [ oFacet.uvwIdx1, oFacet.uvwIdx2, oFacet.uvwIdx3 ];
 
		// Provide feedback
		debug( i, ":", aVertsA );
 
		// Capture the facet data
		aFacetDatas[ nFacetDataIdx ] = {
			"v": aVertsA,
			"uv": aUVsA,
			"g": oFacet.faceGroupIndex,
			"m": oFacet.materialIndex
		};
 
		// Provide feedback
		debug( "#", nFacetDataIdx, ":", JSON.stringify( aFacetDatas[ nFacetDataIdx ], null, "\t" ) );
 
		// Increment the index
		nFacetDataIdx += 1;
 
		// If the facet is a triangle
		if( oFacet.isTri() ){
			// Next!!
			continue;
		}
 
		// Get the vertex indices for the second triangle
		aVertsB = [ oFacet.vertIdx1, oFacet.vertIdx3, oFacet.vertIdx4 ];
		// Get the UV indices for the second triangle
		aUVsB = [ oFacet.uvwIdx1, oFacet.uvwIdx3, oFacet.uvwIdx4 ];
 
		// Provide feedback
		debug( i, ":", aVertsB );
 
		// Capture the facet data
		aFacetDatas[ nFacetDataIdx ] = {
			"v": aVertsB,
			"uv": aUVsB,
			"g": oFacet.faceGroupIndex,
			"m": oFacet.materialIndex
		};
 
		// Provide feedback
		debug( "#", nFacetDataIdx, ":", JSON.stringify( aFacetDatas[ nFacetDataIdx ], null, "\t" ) );
 
		// Increment the index
		nFacetDataIdx += 1;
	}
 
	// Remove 'empty' elements from the list
	aFacetDatas = aFacetDatas.filter( Boolean );
 
	// Get the current shape for the node
	var oShape = getShapeForNode( oNode, true );
 
	// Get the working geometry for the current shape
	var oGeometry = oShape.getCurrentGeometry( DzShape.WorkingGeometry );
 
	// Switch the mesh we are using to a copy of the working geometry - do not share vertices or facets;
	// we only want to modify the mesh for the selected node, not every instance in the scene
	oMesh = oGeometry.makeCopy( false, false );
 
	// If the mesh does not inherit DzFacetMesh
	if( !oMesh.inherits( "DzFacetMesh" ) ){
		// We are done...
		return;
	}
 
	// Declare working variable
	var oUVmap;
 
	// Define whether or not we want a new facet set
	var bNewFacetSet = false;
 
	// If we want a new facet set
	if( bNewFacetSet ){
		// Get the current UV map
		oUVmap = oMesh.getUVs();
 
		// Create a new facet set (LOD); capture the index
		var nFacetSet = oMesh.createFacetSet( "Quads from Tris" );
		// If the active facet set is not our new one
		if( oMesh.getActiveFacetSet() != nFacetSet ){
			// Make our facet set the active one
			oMesh.setActiveFacetSet( nFacetSet );
		}
	}
 
	// Start editing the mesh
	oMesh.beginEdit();
 
	// If we do not want a new facet set
	if( !bNewFacetSet ){
		// Remove all existing facets; keep surfaces and face groups
		oMesh.removeAllFacets( false, false );
		// Remove all existing UV sets
		oMesh.removeAllUVSets();
	// If we want a new facet set
	} else {
		// Now that our facet set is created,
		// cause the existing UV map to be used
		oMesh.setUVList( oUVmap );
 
		// Iterate over the list of face groups
		for( var i = 0; i < nFaceGroups; i += 1 ){
			// Create the 'current' face group for our facet set
			oMesh.createFaceGroup( aFaceGroups[ i ] );
		}
 
		// Iterate over the list of surfaces
		for( var i = 0; i < nSurfaces; i += 1 ){
			// Create the 'current' surface for our facet set
			oMesh.createMaterialGroup( aSurfaceNames[ i ] );
		}
	}
 
	// Declare working variable
	var oFacetData;
 
	// Get the number of facet data objects
	var nNewFacets = aFacetDatas.length;
 
	// Pre-size the number of facets for our facet set
	oMesh.preSizeFacets( nNewFacets );
 
	// Iterate over the list of facet data objects
	for( var i = 0; i < nNewFacets; i += 1 ){
		// Get the 'current' facet data object
		oFacetData = aFacetDatas[ i ];
 
		// Create a new facet
		oFacet = new DzFacet();
 
		// Assign vertex indices
		oFacet.vertIdx1 = oFacetData[ "v" ][ 0 ];
		oFacet.vertIdx2 = oFacetData[ "v" ][ 1 ];
		oFacet.vertIdx3 = oFacetData[ "v" ][ 2 ];
		oFacet.vertIdx4 = -1;
 
		// Assign normal indices
		oFacet.normalIdx1 = oFacetData[ "v" ][ 0 ];
		oFacet.normalIdx2 = oFacetData[ "v" ][ 1 ];
		oFacet.normalIdx3 = oFacetData[ "v" ][ 2 ];
		oFacet.normalIdx4 = -1;
 
		// Assign UV indices
		oFacet.uvwIdx1 = oFacetData[ "uv" ][ 0 ];
		oFacet.uvwIdx2 = oFacetData[ "uv" ][ 1 ];
		oFacet.uvwIdx3 = oFacetData[ "uv" ][ 2 ];
		oFacet.uvwIdx4 = -1;
 
		// Assign face group
		oMesh.activateFaceGroup( oFacetData[ "g" ] );
 
		// Assign surface
		oMesh.activateMaterial( oFacetData[ "m" ] );
 
		// Add the facet to the mesh (for our facet set)
		oMesh.addFacet( oFacet );
	}
 
	// We are done editing the mesh
	oMesh.finishEdit();
 
	// Set the facet mesh
	oShape.setFacetMesh( oMesh );
 
// Finalize the function and invoke
})();