Home | History | Annotate | Download | only in a3dconvert
      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