/* * Copyright 2006 Sony Computer Entertainment Inc. * * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: * http://research.scea.com/scea_shared_source_license.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing permissions and limitations under the * License. */ #include "daeWriter.h" #include #include #include #include #include #include #include //#include #include using namespace osgDAE; domGeometry* daeWriter::getOrCreateDomGeometry(osg::Geometry* pOsgGeometry) { // See if geometry exists in cache OsgGeometryDomGeometryMap::iterator iter = geometryMap.find( pOsgGeometry ); if ( iter != geometryMap.end() ) { return iter->second; } else { if (!lib_geoms) { lib_geoms = daeSafeCast< domLibrary_geometries >( dom->add( COLLADA_ELEMENT_LIBRARY_GEOMETRIES ) ); } domGeometry* pDomGeometry = daeSafeCast< domGeometry >( lib_geoms->add( COLLADA_ELEMENT_GEOMETRY ) ); std::string name = pOsgGeometry->getName(); if (name.empty()) name = uniquify("geometry"); else name = uniquify(name); pDomGeometry->setId( name.c_str() ); #ifndef EARTH_GEO geometryMap.insert( std::make_pair( pOsgGeometry, pDomGeometry ) ); #endif if ( !processGeometry( pOsgGeometry, pDomGeometry, name ) ) { daeElement::removeFromParent( pDomGeometry ); return NULL; } return pDomGeometry; } } void daeWriter::writeRigGeometry(osgAnimation::RigGeometry *pOsgRigGeometry) { // See if controller exists in cache OsgRigGeometryDomControllerMap::iterator iter = _osgRigGeometryDomControllerMap.find(pOsgRigGeometry); domController* pDomController = NULL; if ( iter != _osgRigGeometryDomControllerMap.end() ) { pDomController = iter->second; } else { domGeometry* pDomGeometry = getOrCreateDomGeometry(pOsgRigGeometry); if (pDomGeometry) { if (!lib_controllers) { lib_controllers = daeSafeCast< domLibrary_controllers >( dom->add( COLLADA_ELEMENT_LIBRARY_CONTROLLERS ) ); } // // 1 // source // 0..1 // 3..* // 1 // 1 // 0..1 pDomController = daeSafeCast< domController >( lib_controllers->add( COLLADA_ELEMENT_CONTROLLER) ); std::string name = pOsgRigGeometry->getName(); if (name.empty()) name = uniquify("skincontroller"); else name = uniquify(name); pDomController->setId( name.c_str() ); _osgRigGeometryDomControllerMap.insert( std::make_pair( pOsgRigGeometry, pDomController ) ); // Link to cache hit or created domSkin* pDomSkin = daeSafeCast< domSkin >(pDomController->add( COLLADA_ELEMENT_SKIN )); std::string url = "#" + std::string(pDomGeometry->getId()); pDomSkin->setSource(url.c_str()); domSource* pDomJointsSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE )); std::string skinJointsName = name + "_skin_joints"; pDomJointsSource->setId(skinJointsName.c_str()); domListOfNames jointNames; // TODO fill with joint ids int size = 0; // TODO number of animated joints osgAnimation::VertexInfluenceMap* vim = pOsgRigGeometry->getInfluenceMap(); osgAnimation::VertexInfluenceMap::iterator iter = vim->begin(); while (iter != vim->end()) { jointNames.append(iter->first.c_str()); //iter->second.getn ++iter; } domName_array* pDomJointsNameArray = daeSafeCast< domName_array >(pDomJointsSource->add(COLLADA_ELEMENT_NAME_ARRAY)); std::string jointsNameArrayName = name + "_joints_array"; pDomJointsNameArray->setId(jointsNameArrayName.c_str()); pDomJointsNameArray->setCount(size); pDomJointsNameArray->setValue(jointNames); { domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomJointsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR)); std::string url = "#" + jointsNameArrayName; pDomAccessor->setSource(url.c_str()); pDomAccessor->setCount(size); domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM)); pDomParam->setType(COLLADA_TYPE_NAME); } domSource* pDomSkinBindPoseSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE )); std::string skinBindPoseName = name + "_skin_bind_pose"; pDomSkinBindPoseSource->setId(skinBindPoseName.c_str()); domListOfFloats matrices; // TODO fill with bind matrices int numMatrices = 0; // TODO number of bind matrices domFloat_array* pDomMatricesArray = daeSafeCast< domFloat_array >(pDomSkinBindPoseSource->add(COLLADA_ELEMENT_FLOAT_ARRAY)); std::string matricesArrayName = name + "_matrices_array"; pDomMatricesArray->setId(matricesArrayName.c_str()); pDomMatricesArray->setCount(numMatrices); pDomMatricesArray->setValue(matrices); { domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSkinBindPoseSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR)); std::string url = "#" + matricesArrayName; pDomAccessor->setSource(url.c_str()); pDomAccessor->setCount(size); pDomAccessor->setStride(16); domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM)); pDomParam->setType(COLLADA_TYPE_FLOAT4X4); } domSource* pDomSkinWeightsSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE )); std::string skinWeightsName = name + "_skin_weights"; pDomSkinWeightsSource->setId(skinWeightsName.c_str()); domListOfFloats weights; // TODO fill with vertex weights int numWeights = 0; // TODO number of vertices vertex weights domFloat_array* pDomWeightsArray = daeSafeCast< domFloat_array >(pDomSkinWeightsSource->add(COLLADA_ELEMENT_FLOAT_ARRAY)); std::string weightsArrayName = name + "_weights_array"; pDomWeightsArray->setId(weightsArrayName.c_str()); pDomWeightsArray->setCount(numWeights); pDomWeightsArray->setValue(weights); { domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSkinWeightsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR)); std::string url = "#" + weightsArrayName; pDomAccessor->setSource(url.c_str()); pDomAccessor->setCount(size); domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM)); pDomParam->setType(COLLADA_TYPE_FLOAT); } domSkin::domJoints* pDomJoints = daeSafeCast< domSkin::domJoints >(pDomSkin->add( COLLADA_ELEMENT_JOINTS )); domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomJoints->add(COLLADA_ELEMENT_INPUT)); pDomInput->setSemantic(COMMON_PROFILE_INPUT_JOINT); url = "#" + skinJointsName; pDomInput->setSource(url.c_str()); pDomInput = daeSafeCast< domInputLocal >(pDomJoints->add(COLLADA_ELEMENT_INPUT)); pDomInput->setSemantic(COMMON_PROFILE_INPUT_INV_BIND_MATRIX); url = "#" + skinBindPoseName; pDomInput->setSource(url.c_str()); domSkin::domVertex_weights* pDomVertexWeights = daeSafeCast< domSkin::domVertex_weights >(pDomSkin->add( COLLADA_ELEMENT_VERTEX_WEIGHTS )); pDomVertexWeights->setCount(0);// TODO set number of vertex weights domInputLocalOffset* pDomInputLocalOffset = daeSafeCast< domInputLocalOffset >(pDomVertexWeights->add(COLLADA_ELEMENT_INPUT)); pDomInputLocalOffset->setSemantic(COMMON_PROFILE_INPUT_JOINT); url = "#" + skinJointsName; pDomInputLocalOffset->setSource(url.c_str()); pDomInputLocalOffset->setOffset(0); pDomInputLocalOffset = daeSafeCast< domInputLocalOffset >(pDomVertexWeights->add(COLLADA_ELEMENT_INPUT)); pDomInputLocalOffset->setSemantic(COMMON_PROFILE_INPUT_WEIGHT); url = "#" + weightsArrayName; pDomInputLocalOffset->setSource(url.c_str()); pDomInputLocalOffset->setOffset(1); domSkin::domVertex_weights::domVcount* pDomVcount = daeSafeCast< domSkin::domVertex_weights::domVcount >(pDomVertexWeights->add(COLLADA_ELEMENT_VCOUNT)); domListOfUInts valueCounts; // TODO pDomVcount->setValue(valueCounts); domSkin::domVertex_weights::domV* pDomV = daeSafeCast< domSkin::domVertex_weights::domV >(pDomVertexWeights->add(COLLADA_ELEMENT_V)); domListOfInts values; //TODO pDomV->setValue(values); } } if (pDomController) { // Link to cache hit or created domInstance_controller* pDomInstanceController = daeSafeCast< domInstance_controller >( currentNode->add( COLLADA_ELEMENT_INSTANCE_CONTROLLER ) ); std::string url = "#" + std::string(pDomController->getId()); pDomInstanceController->setUrl( url.c_str() ); } } void daeWriter::writeMorphGeometry(osgAnimation::MorphGeometry *pOsgMorphGeometry) { // See if controller exists in cache OsgMorphGeometryDomControllerMap::iterator iter = _osgMorphGeometryDomControllerMap.find(pOsgMorphGeometry); domController* pDomController = NULL; if ( iter != _osgMorphGeometryDomControllerMap.end() ) { pDomController = iter->second; } else { domGeometry* pDomGeometry = getOrCreateDomGeometry(pOsgMorphGeometry); if (pDomGeometry) { if (!lib_controllers) { lib_controllers = daeSafeCast< domLibrary_controllers >( dom->add( COLLADA_ELEMENT_LIBRARY_CONTROLLERS ) ); } // // 1 // 2..* // 1 // 2..* // 0..* // 0..* pDomController = daeSafeCast< domController >( lib_controllers->add( COLLADA_ELEMENT_CONTROLLER) ); std::string name = pOsgMorphGeometry->getName(); if (name.empty()) name = uniquify("morphcontroller"); else name = uniquify(name); pDomController->setId( name.c_str() ); _osgMorphGeometryDomControllerMap.insert( std::make_pair( pOsgMorphGeometry, pDomController ) ); // Link to cache hit or created domMorph* pDomMorph = daeSafeCast< domMorph >(pDomController->add( COLLADA_ELEMENT_MORPH )); std::string url = "#" + std::string(pDomGeometry->getId()); pDomMorph->setSource(url.c_str()); pDomMorph->setMethod(MORPHMETHODTYPE_NORMALIZED); //pDomMorph->setMethod(MORPHMETHODTYPE_RELATIVE); domSource* pDomTargetsSource = daeSafeCast< domSource >(pDomMorph->add( COLLADA_ELEMENT_SOURCE )); std::string targetsName = name + "_morph_targets"; pDomTargetsSource->setId(targetsName.c_str()); domIDREF_array* pDomIDREFArray = daeSafeCast< domIDREF_array >(pDomTargetsSource->add(COLLADA_ELEMENT_IDREF_ARRAY)); xsIDREFS idrefs; osgAnimation::MorphGeometry::MorphTargetList morphTargetList = pOsgMorphGeometry->getMorphTargetList(); for (unsigned int i=0; i < morphTargetList.size(); i++) { domGeometry* pDomGeometry = getOrCreateDomGeometry(morphTargetList[i].getGeometry()); idrefs.append(pDomGeometry->getId()); } pDomIDREFArray->setValue(idrefs); std::string targetsArrayName = targetsName + "_array"; pDomIDREFArray->setId(targetsArrayName.c_str()); pDomIDREFArray->setCount(morphTargetList.size()); domSource::domTechnique_common* pDomTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomTargetsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR)); pDomAccessor->setCount(morphTargetList.size()); url = "#" + targetsArrayName; pDomAccessor->setSource(url.c_str()); domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM)); pDomParam->setName(COMMON_PROFILE_INPUT_MORPH_TARGET); pDomParam->setType("IDREF"); // COLLADA_TYPE_IDREF does not exist domSource* pDomWeightsSource = daeSafeCast< domSource >(pDomMorph->add( COLLADA_ELEMENT_SOURCE )); std::string weightsName = name + "_morph_weights"; pDomWeightsSource->setId(weightsName.c_str()); domFloat_array* pDomFloatArray = daeSafeCast< domFloat_array >(pDomWeightsSource->add(COLLADA_ELEMENT_FLOAT_ARRAY)); domListOfFloats weights; for (unsigned int i=0; i < morphTargetList.size(); i++) { weights.append(morphTargetList[i].getWeight()); } pDomFloatArray->setValue(weights); std::string weigthsArrayName = weightsName + "_array"; pDomFloatArray->setId(weigthsArrayName.c_str()); pDomFloatArray->setCount(morphTargetList.size()); pDomTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomWeightsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); pDomAccessor = daeSafeCast< domAccessor >(pDomTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR)); pDomAccessor->setCount(morphTargetList.size()); url = "#" + weightsName; pDomAccessor->setSource(url.c_str()); pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM)); pDomParam->setName(COMMON_PROFILE_INPUT_MORPH_WEIGHT); pDomParam->setType(COLLADA_TYPE_FLOAT); domMorph::domTargets* pDomTargets = daeSafeCast< domMorph::domTargets >(pDomMorph->add( COLLADA_ELEMENT_TARGETS )); domInputLocal* pDomTargetsInput = daeSafeCast< domInputLocal >(pDomTargets->add( COLLADA_ELEMENT_INPUT )); pDomTargetsInput->setSemantic(COMMON_PROFILE_INPUT_MORPH_TARGET); url = "#" + targetsName; pDomTargetsInput->setSource(url.c_str()); domInputLocal* pDomWeightsInput = daeSafeCast< domInputLocal >(pDomTargets->add( COLLADA_ELEMENT_INPUT )); pDomWeightsInput->setSemantic(COMMON_PROFILE_INPUT_MORPH_WEIGHT); url = "#" + weightsName; pDomWeightsInput->setSource(url.c_str()); } } if (pDomController) { // Transparency at drawable level if (pOsgMorphGeometry->getStateSet()) m_CurrentRenderingHint = pOsgMorphGeometry->getStateSet()->getRenderingHint(); pushStateSet(pOsgMorphGeometry->getStateSet()); // Link to cache hit or created domInstance_controller* pDomInstanceController = daeSafeCast< domInstance_controller >( currentNode->add( COLLADA_ELEMENT_INSTANCE_CONTROLLER ) ); std::string url = "#" + std::string(pDomController->getId()); pDomInstanceController->setUrl( url.c_str() ); if (!stateSetStack.empty()) { domBind_material *pDomBindMaterial = daeSafeCast< domBind_material >( pDomInstanceController->add( COLLADA_ELEMENT_BIND_MATERIAL ) ); processMaterial( currentStateSet.get(), pDomBindMaterial, pOsgMorphGeometry->getName() ); } popStateSet(pOsgMorphGeometry->getStateSet()); } } void daeWriter::apply( osg::Geode &node ) { debugPrint( node ); pushStateSet(node.getStateSet()); if (NULL != node.getStateSet()) m_CurrentRenderingHint = node.getStateSet()->getRenderingHint(); // TODO // Write a Geode as a single instance_geometry if all drawables use the same vertex streams // Reuse an existing Geode if only statesets differ unsigned int count = node.getNumDrawables(); for ( unsigned int i = 0; i < count; i++ ) { osg::Geometry *g = node.getDrawable( i )->asGeometry(); if ( g != NULL ) { osgAnimation::RigGeometry *pOsgRigGeometry = dynamic_cast(g); if (pOsgRigGeometry) { writeRigGeometry(pOsgRigGeometry); } else { osgAnimation::MorphGeometry *pOsgMorphGeometry = dynamic_cast(g); if (pOsgMorphGeometry) { writeMorphGeometry(pOsgMorphGeometry); } else { // Write a default osg::Geometry // Transparency at drawable level if (NULL != g->getStateSet()) m_CurrentRenderingHint = g->getStateSet()->getRenderingHint(); pushStateSet(g->getStateSet()); domGeometry* pDomGeometry = getOrCreateDomGeometry(g); if (pDomGeometry) { // Link to cache hit or created domInstance_geometry *pDomInstanceGeometry = daeSafeCast< domInstance_geometry >( currentNode->add( COLLADA_ELEMENT_INSTANCE_GEOMETRY ) ); std::string url = "#" + std::string(pDomGeometry->getId()); pDomInstanceGeometry->setUrl( url.c_str() ); if (!stateSetStack.empty()) { domBind_material *pDomBindMaterial = daeSafeCast< domBind_material >( pDomInstanceGeometry->add( COLLADA_ELEMENT_BIND_MATERIAL ) ); processMaterial( currentStateSet.get(), pDomBindMaterial, pDomGeometry->getId() ); } } popStateSet(g->getStateSet()); } } } else { OSG_WARN << "Non-geometry drawables are not supported" << std::endl; } } popStateSet(node.getStateSet()); } /** append elements (verts, normals, colors and texcoord) for file write */ void daeWriter::appendGeometryIndices(osg::Geometry *geom, domP * p, unsigned int vindex, domSource * norm, domSource * color, const ArrayNIndices & verts, const ArrayNIndices & normals, const ArrayNIndices & colors, const std::vector & texcoords, unsigned int ncount, unsigned int ccount) { p->getValue().append( verts.inds!=NULL?verts.inds->index( vindex ):vindex ); if ( norm != NULL ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX ) p->getValue().append( normals.inds!=NULL?normals.inds->index( vindex ):vindex ); else p->getValue().append( normals.inds!=NULL?normals.inds->index( ncount ):ncount ); } if ( color != NULL ) { if ( geom->getColorBinding() == osg::Geometry::BIND_PER_VERTEX ) p->getValue().append( colors.inds!=NULL?colors.inds->index( vindex ):vindex ); else p->getValue().append( colors.inds!=NULL?colors.inds->index( ccount ):ccount ); } for ( unsigned int ti = 0; ti < texcoords.size(); ti++ ) { //ArrayNIndices &tc = texcoords[ti]; p->getValue().append( texcoords[ti].inds!=NULL?texcoords[ti].inds->index(vindex):vindex ); } } bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const std::string &name ) { domMesh *mesh = daeSafeCast< domMesh >( geo->add( COLLADA_ELEMENT_MESH ) ); domSource *pos = NULL; domSource *norm = NULL; domSource *color = NULL; std::vector< domSource * >texcoord; std::vector< domSource * > vertexAttribute; domLines *lines = NULL; domLinestrips *linestrips = NULL; domTriangles *tris = NULL; domTristrips *tristrips = NULL; domTrifans *trifans = NULL; domPolygons *polys = NULL; domPolylist *polylist = NULL; ArrayNIndices verts( geom->getVertexArray(), geom->getVertexIndices() ); ArrayNIndices normals( geom->getNormalArray(), geom->getNormalIndices() ); ArrayNIndices colors( geom->getColorArray(), geom->getColorIndices() ); // RS BUG // getNumTexCoordArrays may return larger number // where getTexCoordArray(0) may have a BIND_OFF and an empty arrat std::vector texcoords; for ( unsigned int i = 0; i < geom->getNumTexCoordArrays(); i++ ) { if (geom->getTexCoordArray(i)) { texcoords.push_back( ArrayNIndices( geom->getTexCoordArray( i ), geom->getTexCoordIndices( i ) ) ); } } std::vector vertexAttributes; for ( unsigned int i = 0; i < geom->getNumVertexAttribArrays(); i++ ) { if (geom->getVertexAttribArray(i)) { vertexAttributes.push_back(ArrayNIndices( geom->getVertexAttribArray( i ), geom->getVertexAttribIndices(i))); } } // process POSITION std::string sName = name + "-positions"; pos = createSource( mesh, sName, verts.mode ); switch( verts.mode ) { case ArrayNIndices::VEC2: pos->getFloat_array()->setCount( verts.vec2->size() *2 ); pos->getTechnique_common()->getAccessor()->setCount( verts.vec2->size() ); for ( unsigned int i = 0; i < verts.vec2->size(); i++ ) { pos->getFloat_array()->getValue().append( (*verts.vec2)[i].x() ); pos->getFloat_array()->getValue().append( (*verts.vec2)[i].y() ); } break; case ArrayNIndices::VEC3: pos->getFloat_array()->setCount( verts.vec3->size() *3 ); pos->getTechnique_common()->getAccessor()->setCount( verts.vec3->size() ); for ( unsigned int i = 0; i < verts.vec3->size(); i++ ) { pos->getFloat_array()->getValue().append( (*verts.vec3)[i].x() ); pos->getFloat_array()->getValue().append( (*verts.vec3)[i].y() ); pos->getFloat_array()->getValue().append( (*verts.vec3)[i].z() ); } break; case ArrayNIndices::VEC4: pos->getFloat_array()->setCount( verts.vec4->size() *4 ); pos->getTechnique_common()->getAccessor()->setCount( verts.vec4->size() ); for ( unsigned int i = 0; i < verts.vec4->size(); i++ ) { pos->getFloat_array()->getValue().append( (*verts.vec4)[i].x() ); pos->getFloat_array()->getValue().append( (*verts.vec4)[i].y() ); pos->getFloat_array()->getValue().append( (*verts.vec4)[i].z() ); pos->getFloat_array()->getValue().append( (*verts.vec4)[i].w() ); } break; default: OSG_WARN << "Invalid array type for vertices" << std::endl; break; } //create a vertices element domVertices *vertices = daeSafeCast< domVertices >( mesh->add( COLLADA_ELEMENT_VERTICES ) ); std::string vName = name + "-vertices"; vertices->setId( vName.c_str() ); //make a POSITION input in it domInputLocal *il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT ) ); il->setSemantic( COMMON_PROFILE_INPUT_POSITION ); std::string url = "#" + std::string( pos->getId() ); il->setSource( url.c_str() ); //process NORMAL if ( normals.mode != ArrayNIndices::NONE ) { sName = name + "-normals"; norm = createSource( mesh, sName, normals.mode ); switch( normals.mode ) { case ArrayNIndices::VEC2: norm->getFloat_array()->setCount( normals.vec2->size() *2 ); norm->getTechnique_common()->getAccessor()->setCount( normals.vec2->size() ); for ( unsigned int i = 0; i < normals.vec2->size(); i++ ) { norm->getFloat_array()->getValue().append( (*normals.vec2)[i].x() ); norm->getFloat_array()->getValue().append( (*normals.vec2)[i].y() ); } break; case ArrayNIndices::VEC3: norm->getFloat_array()->setCount( normals.vec3->size() *3 ); norm->getTechnique_common()->getAccessor()->setCount( normals.vec3->size() ); for ( unsigned int i = 0; i < normals.vec3->size(); i++ ) { norm->getFloat_array()->getValue().append( (*normals.vec3)[i].x() ); norm->getFloat_array()->getValue().append( (*normals.vec3)[i].y() ); norm->getFloat_array()->getValue().append( (*normals.vec3)[i].z() ); } break; case ArrayNIndices::VEC4: norm->getFloat_array()->setCount( normals.vec4->size() *4 ); norm->getTechnique_common()->getAccessor()->setCount( normals.vec4->size() ); for ( unsigned int i = 0; i < normals.vec4->size(); i++ ) { norm->getFloat_array()->getValue().append( (*normals.vec4)[i].x() ); norm->getFloat_array()->getValue().append( (*normals.vec4)[i].y() ); norm->getFloat_array()->getValue().append( (*normals.vec4)[i].z() ); norm->getFloat_array()->getValue().append( (*normals.vec4)[i].w() ); } break; //no normals case ArrayNIndices::NONE: OSG_WARN << "No array type for normals"<( vertices->add( COLLADA_ELEMENT_INPUT ) ); il->setSemantic( COMMON_PROFILE_INPUT_NORMAL ); url = "#" + std::string(md->norm->getId()); il->setSource( url.c_str() ); }*/ } //process COLOR if ( colors.mode != ArrayNIndices::NONE ) { sName = name + "-colors"; color = createSource( mesh, sName, colors.mode, true ); switch( colors.mode ) { case ArrayNIndices::VEC2: color->getFloat_array()->setCount( colors.vec2->size() *2 ); color->getTechnique_common()->getAccessor()->setCount( colors.vec2->size() ); for ( unsigned int i = 0; i < colors.vec2->size(); i++ ) { color->getFloat_array()->getValue().append( (*colors.vec2)[i].x() ); color->getFloat_array()->getValue().append( (*colors.vec2)[i].y() ); } break; case ArrayNIndices::VEC3: color->getFloat_array()->setCount( colors.vec3->size() *3 ); color->getTechnique_common()->getAccessor()->setCount( colors.vec3->size() ); for ( unsigned int i = 0; i < colors.vec3->size(); i++ ) { color->getFloat_array()->getValue().append( (*colors.vec3)[i].x() ); color->getFloat_array()->getValue().append( (*colors.vec3)[i].y() ); color->getFloat_array()->getValue().append( (*colors.vec3)[i].z() ); } break; case ArrayNIndices::VEC4: color->getFloat_array()->setCount( colors.vec4->size() *4 ); color->getTechnique_common()->getAccessor()->setCount( colors.vec4->size() ); for ( unsigned int i = 0; i < colors.vec4->size(); i++ ) { color->getFloat_array()->getValue().append( (*colors.vec4)[i].r() ); color->getFloat_array()->getValue().append( (*colors.vec4)[i].g() ); color->getFloat_array()->getValue().append( (*colors.vec4)[i].b() ); color->getFloat_array()->getValue().append( (*colors.vec4)[i].a() ); } break; default: OSG_WARN << "Invalid array type for colors" << std::endl; break; } //if COLOR shares same indices as POSITION put it in the vertices /*if ( colorInds == vertInds && vertInds != NULL ) { il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT ) ); il->setSemantic( COMMON_PROFILE_INPUT_COLOR ); url = "#" + std::string(md->color->getId()); il->setSource( url.c_str() ); }*/ } //process TEXCOORD //TODO: Do the same as normal and colors for texcoods. But in a loop since you can have many for ( unsigned int ti = 0; ti < texcoords.size(); ti++ ) { std::ostringstream intstr; intstr << std::dec << ti; sName = name + "-texcoord_" + intstr.str(); domSource *t = createSource( mesh, sName, texcoords[ti].mode, false, true ); switch( texcoords[ti].mode ) { case ArrayNIndices::VEC2: t->getFloat_array()->setCount( texcoords[ti].vec2->size() *2 ); t->getTechnique_common()->getAccessor()->setCount( texcoords[ti].vec2->size() ); for ( unsigned int i = 0; i < texcoords[ti].vec2->size(); i++ ) { t->getFloat_array()->getValue().append( (*texcoords[ti].vec2)[i].x() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec2)[i].y() ); } break; case ArrayNIndices::VEC3: t->getFloat_array()->setCount( texcoords[ti].vec3->size() *3 ); t->getTechnique_common()->getAccessor()->setCount( texcoords[ti].vec3->size() ); for ( unsigned int i = 0; i < texcoords[ti].vec3->size(); i++ ) { t->getFloat_array()->getValue().append( (*texcoords[ti].vec3)[i].x() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec3)[i].y() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec3)[i].z() ); } break; case ArrayNIndices::VEC4: t->getFloat_array()->setCount( texcoords[ti].vec4->size() *4 ); t->getTechnique_common()->getAccessor()->setCount( texcoords[ti].vec4->size() ); for ( unsigned int i = 0; i < texcoords[ti].vec4->size(); i++ ) { t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].x() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].y() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].z() ); t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].w() ); } break; default: //##ti and not i OSG_WARN << "Invalid array type for texcoord" << ti << std::endl; break; } texcoord.push_back( t ); } //RS //process TEXCOORD //TODO: Do the same as normal and colors for texcoods. But in a loop since you can have many for ( unsigned int ti = 0; ti < vertexAttributes.size(); ti++ ) { if (vertexAttributes[ti].mode != ArrayNIndices::NONE) { std::ostringstream intstr; intstr << std::dec << ti; sName = name + "-vertexAttribute_" + intstr.str(); domSource *t = createSource( mesh, sName, vertexAttributes[ti].mode, false, true ); switch( vertexAttributes[ti].mode ) { case ArrayNIndices::VEC2: t->getFloat_array()->setCount( vertexAttributes[ti].vec2->size() *2 ); t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec2->size() ); for ( unsigned int i = 0; i < vertexAttributes[ti].vec2->size(); i++ ) { t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec2)[i].x() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec2)[i].y() ); } break; case ArrayNIndices::VEC3: t->getFloat_array()->setCount( vertexAttributes[ti].vec3->size() *3 ); t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec3->size() ); for ( unsigned int i = 0; i < vertexAttributes[ti].vec3->size(); i++ ) { t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].x() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].y() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].z() ); } break; case ArrayNIndices::VEC4: t->getFloat_array()->setCount( vertexAttributes[ti].vec4->size() *4 ); t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec4->size() ); for ( unsigned int i = 0; i < vertexAttributes[ti].vec4->size(); i++ ) { t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].x() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].y() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].z() ); t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].w() ); } break; default: //##ti and not i OSG_WARN << "Invalid array type for vertex attribute" << ti << std::endl; break; } vertexAttribute.push_back( t ); } else { OSG_WARN << "Invalid array type for vertex attribute" << ti << std::endl; } } //process each primitive group unsigned int ncount = 0; //Normal index counter unsigned int ccount = 0; //Color index counter if ( geom->getNumPrimitiveSets() == 0 ) { OSG_WARN << "NO PRIMITIVE SET!!" << std::endl; return false; } bool valid = false; //for each primitive group for ( unsigned int i = 0; i < geom->getNumPrimitiveSets(); i++ ) { osg::PrimitiveSet *ps = geom->getPrimitiveSet( i ); GLenum mode = ps->getMode(); unsigned int primLength; //unsigned int offset = 0; //domInputLocalOffset *ilo = NULL; //process primitive group switch( mode ) { case GL_POINTS: { OSG_WARN << "Geometry contains points rendering. COLLADA does not" << std::endl; continue; } case GL_LINES: { if ( lines == NULL ) { lines = createPrimGroup( COLLADA_ELEMENT_LINES, mesh, norm, color, texcoord ); lines->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; lines->setMaterial( mat.c_str() ); } primLength = 2; valid = true; break; } case GL_TRIANGLES: { if ( tris == NULL ) { tris = createPrimGroup( COLLADA_ELEMENT_TRIANGLES, mesh, norm, color, texcoord ); tris->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; tris->setMaterial( mat.c_str() ); } primLength = 3; valid = true; break; } case GL_QUADS: { if ( polys == NULL ) { if (usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); polys->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polys->setMaterial( mat.c_str() ); } else { polylist = createPrimGroup( COLLADA_ELEMENT_POLYLIST, mesh, norm, color, texcoord ); polylist->add( COLLADA_ELEMENT_VCOUNT ); polylist->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polylist->setMaterial( mat.c_str() ); } } primLength = 4; valid = true; break; } case GL_LINE_STRIP: { if ( linestrips == NULL ) { linestrips = createPrimGroup( COLLADA_ELEMENT_LINESTRIPS, mesh, norm, color, texcoord ); std::string mat = name + "_material"; linestrips->setMaterial( mat.c_str() ); } primLength = 0; valid = true; break; } case GL_TRIANGLE_STRIP: { if ( tristrips == NULL ) { tristrips = createPrimGroup( COLLADA_ELEMENT_TRISTRIPS, mesh, norm, color, texcoord ); std::string mat = name + "_material"; tristrips->setMaterial( mat.c_str() ); } primLength = 0; valid = true; break; } case GL_TRIANGLE_FAN: { if ( trifans == NULL ) { trifans = createPrimGroup( COLLADA_ELEMENT_TRIFANS, mesh, norm, color, texcoord ); std::string mat = name + "_material"; trifans->setMaterial( mat.c_str() ); } primLength = 0; valid = true; break; } default: { if ( polys == NULL ) { if (usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); polys->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polys->setMaterial( mat.c_str() ); } else { polylist = createPrimGroup( COLLADA_ELEMENT_POLYLIST, mesh, norm, color, texcoord ); polylist->add( COLLADA_ELEMENT_VCOUNT ); polylist->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polylist->setMaterial( mat.c_str() ); } } primLength = 0; valid = true; break; // compute later when =0. } } //process upon primitive set type // 1- set data source,accumulate count of primitives and write it to file // 2- read data source for primitive set and write it to file switch( ps->getType() ) { //draw arrays (array of contiguous vertices) //(primitive type+begin+end),(primitive type+begin+end)... case osg::PrimitiveSet::DrawArraysPrimitiveType: { //OSG_WARN << "DrawArrays" << std::endl; if ( primLength == 0 ) { primLength = ps->getNumIndices(); } osg::DrawArrays* drawArray = static_cast< osg::DrawArrays* >( ps ); unsigned int vcount = 0; unsigned int indexEnd = drawArray->getFirst() + drawArray->getCount(); std::vector p; switch ( mode ) { case GL_LINES: { p.push_back(lines->getP()); lines->setCount( lines->getCount() + drawArray->getCount()/primLength ); break; } case GL_TRIANGLES: { p.push_back(tris->getP()); tris->setCount( tris->getCount() + drawArray->getCount()/primLength ); break; } case GL_LINE_STRIP: { p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } default: { //TODO : test this case unsigned int nbPolygons=drawArray->getCount()/primLength; if (usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) p.push_back(polys->getP_array()[0]); polys->setCount( polys->getCount() + nbPolygons ); } else { for( unsigned int idx = 0; idx < nbPolygons; ++idx ) polylist->getVcount()->getValue().append( primLength ); p.push_back(polylist->getP()); polylist->setCount( polylist->getCount() + nbPolygons); } break; } } unsigned int indexBegin = drawArray->getFirst(); unsigned int nbVerticesPerPoly=(indexEnd-indexBegin)/p.size(); unsigned int indexPolyEnd = indexBegin+nbVerticesPerPoly; for( unsigned int iPoly = 0; iPoly < p.size(); ++iPoly ) { for (unsigned int vindex=indexBegin; vindex< indexPolyEnd;vindex++) { appendGeometryIndices(geom,p[iPoly],vindex, norm,color, verts,normals,colors,texcoords, ncount,ccount); if ( vcount % primLength == 0 ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ccount++; } } vcount++; } indexBegin+=nbVerticesPerPoly; indexPolyEnd+=nbVerticesPerPoly; } break; } //(primitive type) + (end1),(end2),(end3)... case osg::PrimitiveSet::DrawArrayLengthsPrimitiveType: { //OSG_WARN << "DrawArrayLengths" << std::endl; osg::DrawArrayLengths* drawArrayLengths = static_cast( ps ); unsigned int vindex = drawArrayLengths->getFirst(); for( osg::DrawArrayLengths::iterator primItr = drawArrayLengths->begin(); primItr != drawArrayLengths->end(); ++primItr ) { unsigned int localPrimLength; if ( primLength == 0 ) localPrimLength = *primItr; else localPrimLength = primLength; std::vector p; switch ( mode ) { case GL_LINES: { p.push_back(lines->getP()); lines->setCount( lines->getCount() + (*primItr)/localPrimLength ); break; } case GL_TRIANGLES: { p.push_back(tris->getP()); tris->setCount( tris->getCount() + (*primItr)/localPrimLength ); break; } case GL_LINE_STRIP: { p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } default: { if (usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) p.push_back(polys->getP_array()[0]); polys->setCount( polys->getCount() + 1 ); } else { polylist->getVcount()->getValue().append( localPrimLength ); p.push_back(polylist->getP()); polylist->setCount( polylist->getCount() + 1); } break; } } unsigned int indexBegin = 0; unsigned int nbVerticesPerPoly=*primItr/p.size(); unsigned int indexEnd=indexBegin+nbVerticesPerPoly; for( unsigned int iPoly = 0; iPoly < p.size(); ++iPoly ) { // printf("indexBegin %d,indexPolyEnd %d \n",indexBegin,indexEnd); for( unsigned int primCount = indexBegin; primCount < indexEnd; ++primCount ) { appendGeometryIndices(geom,p[iPoly],vindex, norm,color, verts,normals,colors,texcoords, ncount,ccount); if ( primCount % localPrimLength == 0 ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ccount++; } } vindex++; } indexBegin+=nbVerticesPerPoly; indexEnd+=nbVerticesPerPoly; } } break; } //draw elements (array of shared vertices + array of indices) case osg::PrimitiveSet::DrawElementsUBytePrimitiveType: { //OSG_WARN << "DrawElementsUByte" << std::endl; if ( primLength == 0 ) primLength = ps->getNumIndices(); osg::DrawElementsUByte* drawElements = static_cast( ps ); std::vector p; switch ( mode ) { case GL_LINES: { p.push_back(lines->getP()); lines->setCount( lines->getCount() + drawElements->size()/primLength ); break; } case GL_TRIANGLES: { p.push_back(tris->getP()); tris->setCount( tris->getCount() + drawElements->size()/primLength ); break; } case GL_LINE_STRIP: { p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } default: { unsigned int nbPolygons=drawElements->size()/primLength; if (usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? p.push_back(polys->getP_array()[0]); polys->setCount( polys->getCount() + nbPolygons ); } else { polylist->getVcount()->getValue().append( primLength ); p.push_back(polylist->getP()); polylist->setCount( polylist->getCount() + nbPolygons ); } break; } } unsigned int primCount = 0; osg::DrawElementsUByte::iterator primItrBegin = drawElements->begin(); unsigned int nbVerticesPerPoly= drawElements->size()/p.size(); osg::DrawElementsUByte::iterator primItrEnd=primItrBegin+nbVerticesPerPoly; for( unsigned int iPoly = 0; iPoly < p.size(); ++iPoly ) { for( osg::DrawElementsUByte::iterator primItr = primItrBegin;primItr != primItrEnd; ++primCount, ++primItr ) { unsigned int vindex = *primItr; appendGeometryIndices(geom,p[iPoly],vindex, norm,color, verts,normals,colors,texcoords, ncount,ccount); if ( primCount % primLength == 0 ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ccount++; } } } primItrBegin+=nbVerticesPerPoly; #if ( _SECURE_SCL == 1 ) if (primItrBegin != drawElements->end()) #endif primItrEnd+=nbVerticesPerPoly; } break; } case osg::PrimitiveSet::DrawElementsUShortPrimitiveType: { //OSG_WARN << "DrawElementsUShort" << std::endl; if ( primLength == 0 ) primLength = ps->getNumIndices(); osg::DrawElementsUShort* drawElements = static_cast( ps ); std::vector p; switch ( mode ) { case GL_LINES: { p.push_back(lines->getP()); lines->setCount( lines->getCount() + drawElements->size()/primLength ); break; } case GL_TRIANGLES: { p.push_back(tris->getP()); tris->setCount( tris->getCount() + drawElements->size()/primLength ); break; } case GL_LINE_STRIP: { p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } default: { unsigned int nbPolygons=drawElements->size()/primLength; if (usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? p.push_back(polys->getP_array()[0]); polys->setCount( polys->getCount() + nbPolygons ); } else { polylist->getVcount()->getValue().append( primLength ); p.push_back(polylist->getP()); polylist->setCount( polylist->getCount() + nbPolygons ); } break; } } unsigned int primCount = 0; osg::DrawElementsUShort::iterator primItrBegin = drawElements->begin(); unsigned int nbVerticesPerPoly= drawElements->size()/p.size(); osg::DrawElementsUShort::iterator primItrEnd=primItrBegin+nbVerticesPerPoly; for( unsigned int iPoly = 0; iPoly < p.size(); ++iPoly ) { for( osg::DrawElementsUShort::iterator primItr = primItrBegin;primItr != primItrEnd; ++primCount, ++primItr ) { unsigned int vindex = *primItr; appendGeometryIndices(geom,p[iPoly],vindex, norm,color, verts,normals,colors,texcoords, ncount,ccount); if ( primCount % primLength == 0 ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ccount++; } } } primItrBegin+=nbVerticesPerPoly; #if ( _SECURE_SCL == 1 ) if (primItrBegin != drawElements->end()) #endif primItrEnd+=nbVerticesPerPoly; } break; } case osg::PrimitiveSet::DrawElementsUIntPrimitiveType: { //OSG_WARN << "DrawElementsUInt" << std::endl; if ( primLength == 0 ) primLength = ps->getNumIndices(); osg::DrawElementsUInt* drawElements = static_cast( ps ); std::vector p; switch ( mode ) { case GL_LINES: { p.push_back(lines->getP()); lines->setCount( lines->getCount() + drawElements->size()/primLength ); break; } case GL_TRIANGLES: { p.push_back(tris->getP()); tris->setCount( tris->getCount() + drawElements->size()/primLength ); break; } case GL_LINE_STRIP: { p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } default: { unsigned int nbPolygons=drawElements->size()/primLength; if (usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? p.push_back(polys->getP_array()[0]); polys->setCount( polys->getCount() + nbPolygons ); } else { polylist->getVcount()->getValue().append( primLength ); p.push_back(polylist->getP()); polylist->setCount( polylist->getCount() + nbPolygons ); } break; } } unsigned int primCount = 0; osg::DrawElementsUInt::iterator primItrBegin = drawElements->begin(); unsigned int nbVerticesPerPoly= drawElements->size()/p.size(); osg::DrawElementsUInt::iterator primItrEnd=primItrBegin+nbVerticesPerPoly; for( unsigned int iPoly = 0; iPoly < p.size(); ++iPoly ) { for( osg::DrawElementsUInt::iterator primItr = primItrBegin;primItr != primItrEnd; ++primCount, ++primItr ) { unsigned int vindex = *primItr; appendGeometryIndices(geom,p[iPoly],vindex, norm,color, verts,normals,colors,texcoords, ncount,ccount); if ( primCount % primLength == 0 ) { if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE ) { ccount++; } } } primItrBegin+=nbVerticesPerPoly; #if ( _SECURE_SCL == 1 ) if (primItrBegin != drawElements->end()) #endif primItrEnd+=nbVerticesPerPoly; } break; } default: OSG_WARN << "Unsupported primitiveSet" << std::endl; break; } if ( geom->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET ) { ncount++; } if ( geom->getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET ) { ccount++; } } return valid; } domSource *daeWriter::createSource( daeElement *parent, const std::string &baseName, int size, bool color, bool uv ) { domSource *src = daeSafeCast< domSource >( parent->add( COLLADA_ELEMENT_SOURCE ) ); if ( src == NULL ) { return NULL; } src->setId( baseName.c_str() ); domFloat_array *fa = daeSafeCast< domFloat_array >( src->add( COLLADA_ELEMENT_FLOAT_ARRAY ) ); std::string fName = baseName + "-array"; fa->setId( fName.c_str() ); domSource::domTechnique_common *teq = daeSafeCast< domSource::domTechnique_common >( src->add( COLLADA_ELEMENT_TECHNIQUE_COMMON ) ); domAccessor *acc = daeSafeCast< domAccessor >( teq->add( COLLADA_ELEMENT_ACCESSOR ) ); std::string url = "#" + fName; acc->setSource( url.c_str() ); domParam *param; if ( color ) { acc->setStride( size ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "R" ); param->setType( "float" ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "G" ); param->setType( "float" ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "B" ); param->setType( "float" ); if ( size == 4 ) { param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "A" ); param->setType( "float" ); } } else if ( uv ) { acc->setStride( size ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "S" ); param->setType( "float" ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "T" ); param->setType( "float" ); if ( size >=3 ) { param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "P" ); param->setType( "float" ); } } else { acc->setStride( size ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "X" ); param->setType( "float" ); param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "Y" ); param->setType( "float" ); if ( size >=3 ) { param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "Z" ); param->setType( "float" ); if ( size == 4 ) { param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "W" ); param->setType( "float" ); } } } return src; } template < typename Ty > Ty *daeWriter::createPrimGroup( daeString type, domMesh *mesh, domSource *norm, domSource *color, const std::vector< domSource* > &texcoord ) { unsigned int offset = 0; Ty *retVal = daeSafeCast< Ty >( mesh->add( type ) ); domInputLocalOffset *ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) ); ilo->setOffset( offset++ ); ilo->setSemantic( COMMON_PROFILE_INPUT_VERTEX ); std::string url = "#" + std::string(mesh->getVertices()->getId()); ilo->setSource( url.c_str() ); if ( norm != NULL ) { ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) ); ilo->setOffset( offset++ ); ilo->setSemantic( COMMON_PROFILE_INPUT_NORMAL ); url = "#" + std::string( norm->getId() ); ilo->setSource( url.c_str() ); } if ( color != NULL ) { ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) ); ilo->setOffset( offset++ ); ilo->setSemantic( COMMON_PROFILE_INPUT_COLOR ); url = "#" + std::string( color->getId() ); ilo->setSource( url.c_str() ); } for ( unsigned int i = 0; i < texcoord.size(); i++ ) { ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) ); ilo->setOffset( offset++ ); ilo->setSemantic( COMMON_PROFILE_INPUT_TEXCOORD ); ilo->setSet( i ); url = "#" + std::string( texcoord[i]->getId() ); ilo->setSource( url.c_str() ); } return retVal; }