/* * Copyright 2006 Sony Computer Entertainment Inc. * * Licensed under the MIT Open Source License, for details please see license.txt or the website * http://www.opensource.org/licenses/mit-license.php * */ #include "ColladaConditioner.h" unsigned int ColladaConditioner::getMaxOffset( domInputLocalOffset_Array &input_array ) { unsigned int maxOffset = 0; for ( unsigned int i = 0; i < input_array.getCount(); i++ ) { if ( input_array[i]->getOffset() > maxOffset ) { maxOffset = (unsigned int)input_array[i]->getOffset(); } } return maxOffset; } void ColladaConditioner::createTrianglesFromPolylist( domMesh *thisMesh, domPolylist *thisPolylist ) { // Create a new <triangles> inside the mesh that has the same material as the <polylist> domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles"); //thisTriangles->setCount( 0 ); unsigned int triangles = 0; thisTriangles->setMaterial(thisPolylist->getMaterial()); domP* p_triangles = (domP*)thisTriangles->createAndPlace("p"); // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist> for(int i=0; i<(int)(thisPolylist->getInput_array().getCount()); i++) { thisTriangles->placeElement( thisPolylist->getInput_array()[i]->clone() ); } // Get the number of inputs and primitives for the polygons array int numberOfInputs = (int)getMaxOffset(thisPolylist->getInput_array()) + 1; int numberOfPrimitives = (int)(thisPolylist->getVcount()->getValue().getCount()); unsigned int offset = 0; // Triangulate all the primitives, this generates all the triangles in a single <p> element for(int j = 0; j < numberOfPrimitives; j++) { int triangleCount = (int)thisPolylist->getVcount()->getValue()[j] -2; // Write out the primitives as triangles, just fan using the first element as the base int idx = numberOfInputs; for(int k = 0; k < triangleCount; k++) { // First vertex for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + l]); } // Second vertex for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]); } // Third vertex idx += numberOfInputs; for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]); } triangles++; } offset += (unsigned int)thisPolylist->getVcount()->getValue()[j] * numberOfInputs; } thisTriangles->setCount( triangles ); } void ColladaConditioner::createTrianglesFromPolygons( domMesh *thisMesh, domPolygons *thisPolygons ) { // Create a new <triangles> inside the mesh that has the same material as the <polygons> domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles"); thisTriangles->setCount( 0 ); thisTriangles->setMaterial(thisPolygons->getMaterial()); domP* p_triangles = (domP*)thisTriangles->createAndPlace("p"); // Give the new <triangles> the same <_dae> and <parameters> as the old <polygons> for(int i=0; i<(int)(thisPolygons->getInput_array().getCount()); i++) { thisTriangles->placeElement( thisPolygons->getInput_array()[i]->clone() ); } // Get the number of inputs and primitives for the polygons array int numberOfInputs = (int)getMaxOffset(thisPolygons->getInput_array()) +1; int numberOfPrimitives = (int)(thisPolygons->getP_array().getCount()); // Triangulate all the primitives, this generates all the triangles in a single <p> element for(int j = 0; j < numberOfPrimitives; j++) { // Check the polygons for consistancy (some exported files have had the wrong number of indices) domP * thisPrimitive = thisPolygons->getP_array()[j]; int elementCount = (int)(thisPrimitive->getValue().getCount()); // Skip the invalid primitive if((elementCount % numberOfInputs) != 0) { continue; } else { int triangleCount = (elementCount/numberOfInputs)-2; // Write out the primitives as triangles, just fan using the first element as the base int idx = numberOfInputs; for(int k = 0; k < triangleCount; k++) { // First vertex for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPrimitive->getValue()[l]); } // Second vertex for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]); } // Third vertex idx += numberOfInputs; for(int l = 0; l < numberOfInputs; l++) { p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]); } thisTriangles->setCount(thisTriangles->getCount()+1); } } } } bool ColladaConditioner::triangulate(DAE *dae) { int error = 0; // How many geometry elements are there? int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "geometry" )); for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) { // Find the next geometry element domGeometry *thisGeometry; // error = _dae->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry, NULL, "geometry"); daeElement * element = 0; error = dae->getDatabase()->getElement(&element,currentGeometry, NULL, "geometry"); thisGeometry = (domGeometry *) element; // Get the mesh out of the geometry domMesh *thisMesh = thisGeometry->getMesh(); if (thisMesh == NULL){ continue; } // Loop over all the polygon elements for(int currentPolygons = 0; currentPolygons < (int)(thisMesh->getPolygons_array().getCount()); currentPolygons++) { // Get the polygons out of the mesh // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it domPolygons *thisPolygons = thisMesh->getPolygons_array()[currentPolygons]; createTrianglesFromPolygons( thisMesh, thisPolygons ); } while (thisMesh->getPolygons_array().getCount() > 0) { domPolygons *thisPolygons = thisMesh->getPolygons_array().get(0); // Remove the polygons from the mesh thisMesh->removeChildElement(thisPolygons); } int polylistElementCount = (int)(thisMesh->getPolylist_array().getCount()); for(int currentPolylist = 0; currentPolylist < polylistElementCount; currentPolylist++) { // Get the polylist out of the mesh // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it domPolylist *thisPolylist = thisMesh->getPolylist_array()[currentPolylist]; createTrianglesFromPolylist( thisMesh, thisPolylist ); } while (thisMesh->getPolylist_array().getCount() > 0) { domPolylist *thisPolylist = thisMesh->getPolylist_array().get(0); // Remove the polylist from the mesh thisMesh->removeChildElement(thisPolylist); } } return (error == 0); } bool ColladaConditioner::triangulate(const char *inputFile) { DAE dae; bool convertSuceeded = true; domCOLLADA* root = dae.open(inputFile); if (!root) { printf("Failed to read file %s.\n", inputFile); return false; } convertSuceeded = triangulate(&dae); dae.writeAll(); if(!convertSuceeded) { printf("Encountered errors\n"); } return convertSuceeded; } bool ColladaConditioner::stripGeometry(DAE *dae) { bool convertSuceeded = true; int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "library_geometries" )); for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) { daeElement * element = 0; int error = dae->getDatabase()->getElement(&element, currentGeometry, NULL, "library_geometries"); daeBool removed = daeElement::removeFromParent(element); convertSuceeded = convertSuceeded && removed; } return convertSuceeded; } bool ColladaConditioner::stripGeometry(const char *inputFile) { DAE dae; bool convertSuceeded = true; domCOLLADA* root = dae.open(inputFile); if (!root) { printf("Failed to read file %s.\n", inputFile); return false; } stripGeometry(&dae); dae.writeAll(); if(!convertSuceeded) { printf("Encountered errors\n"); } return convertSuceeded; }