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"
getMaxOffset(domInputLocalOffset_Array & input_array)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
createTrianglesFromPolylist(domMesh * thisMesh,domPolylist * thisPolylist)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
createTrianglesFromPolygons(domMesh * thisMesh,domPolygons * thisPolygons)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
triangulate(DAE * dae)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
triangulate(const char * inputFile)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
stripGeometry(DAE * dae)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
stripGeometry(const char * inputFile)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