1 /* 2 * Copyright 2006 Sony Computer Entertainment Inc. 3 * 4 * Licensed under the MIT Open Source License, for details please see license.txt or the website 5 * http://www.opensource.org/licenses/mit-license.php 6 * 7 */ 8 9 #include "ColladaConditioner.h" 10 unsigned int ColladaConditioner::getMaxOffset( domInputLocalOffset_Array &input_array ) { 11 12 unsigned int maxOffset = 0; 13 for ( unsigned int i = 0; i < input_array.getCount(); i++ ) { 14 if ( input_array[i]->getOffset() > maxOffset ) { 15 maxOffset = (unsigned int)input_array[i]->getOffset(); 16 } 17 } 18 return maxOffset; 19 } 20 21 void ColladaConditioner::createTrianglesFromPolylist( domMesh *thisMesh, domPolylist *thisPolylist ) { 22 23 // Create a new <triangles> inside the mesh that has the same material as the <polylist> 24 domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles"); 25 //thisTriangles->setCount( 0 ); 26 unsigned int triangles = 0; 27 thisTriangles->setMaterial(thisPolylist->getMaterial()); 28 domP* p_triangles = (domP*)thisTriangles->createAndPlace("p"); 29 30 // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist> 31 for(int i=0; i<(int)(thisPolylist->getInput_array().getCount()); i++) { 32 33 thisTriangles->placeElement( thisPolylist->getInput_array()[i]->clone() ); 34 } 35 36 // Get the number of inputs and primitives for the polygons array 37 int numberOfInputs = (int)getMaxOffset(thisPolylist->getInput_array()) + 1; 38 int numberOfPrimitives = (int)(thisPolylist->getVcount()->getValue().getCount()); 39 40 unsigned int offset = 0; 41 42 // Triangulate all the primitives, this generates all the triangles in a single <p> element 43 for(int j = 0; j < numberOfPrimitives; j++) { 44 45 int triangleCount = (int)thisPolylist->getVcount()->getValue()[j] -2; 46 // Write out the primitives as triangles, just fan using the first element as the base 47 int idx = numberOfInputs; 48 for(int k = 0; k < triangleCount; k++) { 49 // First vertex 50 for(int l = 0; l < numberOfInputs; l++) { 51 52 p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + l]); 53 } 54 // Second vertex 55 for(int l = 0; l < numberOfInputs; l++) { 56 57 p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]); 58 } 59 // Third vertex 60 idx += numberOfInputs; 61 for(int l = 0; l < numberOfInputs; l++) { 62 63 p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]); 64 } 65 triangles++; 66 } 67 offset += (unsigned int)thisPolylist->getVcount()->getValue()[j] * numberOfInputs; 68 } 69 thisTriangles->setCount( triangles ); 70 71 } 72 73 void ColladaConditioner::createTrianglesFromPolygons( domMesh *thisMesh, domPolygons *thisPolygons ) { 74 75 // Create a new <triangles> inside the mesh that has the same material as the <polygons> 76 domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles"); 77 thisTriangles->setCount( 0 ); 78 thisTriangles->setMaterial(thisPolygons->getMaterial()); 79 domP* p_triangles = (domP*)thisTriangles->createAndPlace("p"); 80 81 // Give the new <triangles> the same <_dae> and <parameters> as the old <polygons> 82 for(int i=0; i<(int)(thisPolygons->getInput_array().getCount()); i++) { 83 84 thisTriangles->placeElement( thisPolygons->getInput_array()[i]->clone() ); 85 } 86 87 // Get the number of inputs and primitives for the polygons array 88 int numberOfInputs = (int)getMaxOffset(thisPolygons->getInput_array()) +1; 89 int numberOfPrimitives = (int)(thisPolygons->getP_array().getCount()); 90 91 // Triangulate all the primitives, this generates all the triangles in a single <p> element 92 for(int j = 0; j < numberOfPrimitives; j++) { 93 94 // Check the polygons for consistancy (some exported files have had the wrong number of indices) 95 domP * thisPrimitive = thisPolygons->getP_array()[j]; 96 int elementCount = (int)(thisPrimitive->getValue().getCount()); 97 // Skip the invalid primitive 98 if((elementCount % numberOfInputs) != 0) { 99 continue; 100 } else { 101 int triangleCount = (elementCount/numberOfInputs)-2; 102 // Write out the primitives as triangles, just fan using the first element as the base 103 int idx = numberOfInputs; 104 for(int k = 0; k < triangleCount; k++) { 105 // First vertex 106 for(int l = 0; l < numberOfInputs; l++) { 107 108 p_triangles->getValue().append(thisPrimitive->getValue()[l]); 109 } 110 // Second vertex 111 for(int l = 0; l < numberOfInputs; l++) { 112 113 p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]); 114 } 115 // Third vertex 116 idx += numberOfInputs; 117 for(int l = 0; l < numberOfInputs; l++) { 118 119 p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]); 120 } 121 thisTriangles->setCount(thisTriangles->getCount()+1); 122 } 123 } 124 } 125 126 } 127 128 129 bool ColladaConditioner::triangulate(DAE *dae) { 130 131 int error = 0; 132 133 // How many geometry elements are there? 134 int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "geometry" )); 135 136 for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) { 137 138 // Find the next geometry element 139 domGeometry *thisGeometry; 140 // error = _dae->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry, NULL, "geometry"); 141 daeElement * element = 0; 142 error = dae->getDatabase()->getElement(&element,currentGeometry, NULL, "geometry"); 143 thisGeometry = (domGeometry *) element; 144 145 // Get the mesh out of the geometry 146 domMesh *thisMesh = thisGeometry->getMesh(); 147 148 if (thisMesh == NULL){ 149 continue; 150 } 151 152 // Loop over all the polygon elements 153 for(int currentPolygons = 0; currentPolygons < (int)(thisMesh->getPolygons_array().getCount()); currentPolygons++) { 154 155 // Get the polygons out of the mesh 156 // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it 157 domPolygons *thisPolygons = thisMesh->getPolygons_array()[currentPolygons]; 158 createTrianglesFromPolygons( thisMesh, thisPolygons ); 159 } 160 while (thisMesh->getPolygons_array().getCount() > 0) { 161 162 domPolygons *thisPolygons = thisMesh->getPolygons_array().get(0); 163 // Remove the polygons from the mesh 164 thisMesh->removeChildElement(thisPolygons); 165 } 166 int polylistElementCount = (int)(thisMesh->getPolylist_array().getCount()); 167 for(int currentPolylist = 0; currentPolylist < polylistElementCount; currentPolylist++) { 168 169 // Get the polylist out of the mesh 170 // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it 171 domPolylist *thisPolylist = thisMesh->getPolylist_array()[currentPolylist]; 172 createTrianglesFromPolylist( thisMesh, thisPolylist ); 173 } 174 while (thisMesh->getPolylist_array().getCount() > 0) { 175 176 domPolylist *thisPolylist = thisMesh->getPolylist_array().get(0); 177 // Remove the polylist from the mesh 178 thisMesh->removeChildElement(thisPolylist); 179 } 180 } 181 return (error == 0); 182 } 183 184 bool ColladaConditioner::triangulate(const char *inputFile) { 185 186 DAE dae; 187 bool convertSuceeded = true; 188 domCOLLADA* root = dae.open(inputFile); 189 190 if (!root) { 191 printf("Failed to read file %s.\n", inputFile); 192 return false; 193 } 194 195 convertSuceeded = triangulate(&dae); 196 197 dae.writeAll(); 198 if(!convertSuceeded) { 199 printf("Encountered errors\n"); 200 } 201 202 return convertSuceeded; 203 } 204 205 bool ColladaConditioner::stripGeometry(DAE *dae) { 206 bool convertSuceeded = true; 207 int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, 208 "library_geometries" )); 209 210 for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) { 211 212 daeElement * element = 0; 213 int error = dae->getDatabase()->getElement(&element, currentGeometry, 214 NULL, "library_geometries"); 215 daeBool removed = daeElement::removeFromParent(element); 216 convertSuceeded = convertSuceeded && removed; 217 } 218 return convertSuceeded; 219 } 220 221 bool ColladaConditioner::stripGeometry(const char *inputFile) { 222 DAE dae; 223 bool convertSuceeded = true; 224 domCOLLADA* root = dae.open(inputFile); 225 226 if (!root) { 227 printf("Failed to read file %s.\n", inputFile); 228 return false; 229 } 230 231 stripGeometry(&dae); 232 233 dae.writeAll(); 234 if(!convertSuceeded) { 235 printf("Encountered errors\n"); 236 } 237 238 return convertSuceeded; 239 } 240