int main(int argc, char **argv) { // OSG init osgInit(argc,argv); // Set up Window TutorialWindow = createNativeWindow(); TutorialWindow->initWindow(); TutorialWindow->setDisplayCallback(display); TutorialWindow->setReshapeCallback(reshape); //Add Window Listener TutorialKeyListener TheKeyListener; TutorialWindow->addKeyListener(&TheKeyListener); TutorialMouseListener TheTutorialMouseListener; TutorialMouseMotionListener TheTutorialMouseMotionListener; TutorialWindow->addMouseListener(&TheTutorialMouseListener); TutorialWindow->addMouseMotionListener(&TheTutorialMouseMotionListener); // Create the SimpleSceneManager helper mgr = new SimpleSceneManager; // Tell the Manager what to manage mgr->setWindow(TutorialWindow); //Print key command info std::cout << "\n\nKEY COMMANDS:" << std::endl; std::cout << "space Play/Pause the animation" << std::endl; std::cout << "B Show/Hide the bind pose skeleton" << std::endl; std::cout << "SHIFT-B Show/Hide the bind pose mesh" << std::endl; std::cout << "P Show/Hide the current pose skeleton" << std::endl; std::cout << "SHIFT-P Show/Hide the current pose mesh" << std::endl; std::cout << "CTRL-Q Exit\n\n" << std::endl; //SkeletonDrawer System Material LineChunkUnrecPtr ExampleLineChunk = LineChunk::create(); ExampleLineChunk->setWidth(2.0f); ExampleLineChunk->setSmooth(true); BlendChunkUnrecPtr ExampleBlendChunk = BlendChunk::create(); ExampleBlendChunk->setSrcFactor(GL_SRC_ALPHA); ExampleBlendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA); MaterialChunkUnrecPtr ExampleMaterialChunk = MaterialChunk::create(); ExampleMaterialChunk->setAmbient(Color4f(1.0f,1.0f,1.0f,1.0f)); ExampleMaterialChunk->setDiffuse(Color4f(0.0f,0.0f,0.0f,1.0f)); ExampleMaterialChunk->setSpecular(Color4f(0.0f,0.0f,0.0f,1.0f)); ChunkMaterialUnrecPtr ExampleMaterial = ChunkMaterial::create(); ExampleMaterial->addChunk(ExampleLineChunk); ExampleMaterial->addChunk(ExampleMaterialChunk); ExampleMaterial->addChunk(ExampleBlendChunk); //Skeleton ExampleSkeleton = SkeletonBlendedGeometry::create(); //===========================================Joints================================================================== Matrix TempMat; Matrix InvBind; /*================================================================================================*/ /* Pelvis */ Pelvis = Joint::create(); //create a joint called Pelvis TempMat.setTranslate(0.0,7.0,0.0); Pelvis->setJointTransformation(TempMat); NodeRecPtr PelvisNode = makeNodeFor(Pelvis); InvBind = PelvisNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(Pelvis, InvBind); setName(Pelvis, "Pelvis Joint"); setName(PelvisNode, "Pelvis Node"); /*================================================================================================*/ /* Clavicle */ Clavicle = Joint::create(); //create a joint called Clavicle TempMat.setTranslate(0.0,5.0,0.0); Clavicle->setJointTransformation(TempMat); NodeRecPtr ClavicleNode = makeNodeFor(Clavicle); PelvisNode->addChild(ClavicleNode); InvBind = ClavicleNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(Clavicle, InvBind); setName(Clavicle, "Clavicle Joint"); setName(ClavicleNode, "Clavicle Node"); /*================================================================================================*/ /* Left Shoulder */ LeftShoulder = Joint::create(); //create a joint called LeftShoulder TempMat.setTranslate(1.0,-0.5,0.0); LeftShoulder->setJointTransformation(TempMat); NodeRecPtr LeftShoulderNode = makeNodeFor(LeftShoulder); ClavicleNode->addChild(LeftShoulderNode); InvBind = LeftShoulderNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftShoulder, InvBind); setName(LeftShoulder, "Left Shoulder Joint"); setName(LeftShoulderNode, "Left Shoulder Node"); /*================================================================================================*/ /* Left Elbow */ LeftElbow = Joint::create(); //create a joint called LeftElbow TempMat.setTranslate(2.0,0.0,0.0); LeftElbow->setJointTransformation(TempMat); NodeRecPtr LeftElbowNode = makeNodeFor(LeftElbow); LeftShoulderNode->addChild(LeftElbowNode); InvBind = LeftElbowNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftElbow, InvBind); setName(LeftElbow, "Left Elbow Joint"); setName(LeftElbowNode, "Left Elbow Node"); /*================================================================================================*/ /* Left Hand */ LeftHand = Joint::create(); //create a joint called LeftHand TempMat.setTranslate(2.0,0.0,0.0); LeftHand->setJointTransformation(TempMat); NodeRecPtr LeftHandNode = makeNodeFor(LeftHand); LeftElbowNode->addChild(LeftHandNode); InvBind = LeftHandNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftHand, InvBind); setName(LeftHand, "Left Hand Joint"); setName(LeftHandNode, "Left Hand Node"); /*================================================================================================*/ /* Left Fingers */ LeftFingers = Joint::create(); //create a joint called LeftFingers TempMat.setTranslate(1.0,0.0,0.0); LeftFingers->setJointTransformation(TempMat); NodeRecPtr LeftFingersNode = makeNodeFor(LeftFingers); LeftHandNode->addChild(LeftFingersNode); InvBind = LeftFingersNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftFingers, InvBind); setName(LeftFingers, "Left Fingers Joint"); setName(LeftFingersNode, "Left Fingers Node"); /*================================================================================================*/ /* Right Shoulder */ RightShoulder = Joint::create(); //create a joint called RightShoulder TempMat.setTranslate(-1.0,-0.5,0.0); RightShoulder->setJointTransformation(TempMat); NodeRecPtr RightShoulderNode = makeNodeFor(RightShoulder); ClavicleNode->addChild(RightShoulderNode); InvBind = RightShoulderNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightShoulder, InvBind); setName(RightShoulder, "Right Shoulder Joint"); setName(RightShoulderNode, "Right Shoulder Node"); /*================================================================================================*/ /* Right Elbow */ RightElbow = Joint::create(); //create a joint called RightElbow TempMat.setTranslate(-2.0,0.0,0.0); RightElbow->setJointTransformation(TempMat); NodeRecPtr RightElbowNode = makeNodeFor(RightElbow); RightShoulderNode->addChild(RightElbowNode); InvBind = RightElbowNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightElbow, InvBind); setName(RightElbow, "Right Elbow Joint"); setName(RightElbowNode, "Right Elbow Node"); /*================================================================================================*/ /* Right Hand */ RightHand = Joint::create(); //create a joint called RightHand TempMat.setTranslate(-2.0,0.0,0.0); RightHand->setJointTransformation(TempMat); NodeRecPtr RightHandNode = makeNodeFor(RightHand); RightElbowNode->addChild(RightHandNode); InvBind = RightHandNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightHand, InvBind); setName(RightHand, "Right Hand Joint"); setName(RightHandNode, "Right Hand Node"); /*================================================================================================*/ /* Right Fingers */ RightFingers = Joint::create(); //create a joint called RightFingers TempMat.setTranslate(-1.0,0.0,0.0); RightFingers->setJointTransformation(TempMat); NodeRecPtr RightFingersNode = makeNodeFor(RightFingers); RightHandNode->addChild(RightFingersNode); InvBind = RightFingersNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightFingers, InvBind); setName(RightFingers, "Right Fingers Joint"); setName(RightFingersNode, "Right Fingers Node"); /*================================================================================================*/ /* Head */ Head = Joint::create(); //create a joint called Head TempMat.setTranslate(0.0,1.0,0.0); Head->setJointTransformation(TempMat); NodeRecPtr HeadNode = makeNodeFor(Head); ClavicleNode->addChild(HeadNode); InvBind = HeadNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(Head, InvBind); setName(Head, "Head Joint"); setName(HeadNode, "Head Node"); /*================================================================================================*/ /* Left Hip */ LeftHip = Joint::create(); //create a joint called LeftHip TempMat.setTranslate(1.0,-1.0,0.0); LeftHip->setJointTransformation(TempMat); NodeRecPtr LeftHipNode = makeNodeFor(LeftHip); PelvisNode->addChild(LeftHipNode); InvBind = LeftHipNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftHip, InvBind); setName(LeftHip, "Left Hip Joint"); setName(LeftHipNode, "Left Hip Node"); /*================================================================================================*/ /* Left Knee */ LeftKnee = Joint::create(); //create a joint called LeftKnee TempMat.setTranslate(0.0,-3.0,0.0); LeftKnee->setJointTransformation(TempMat); NodeRecPtr LeftKneeNode = makeNodeFor(LeftKnee); LeftHipNode->addChild(LeftKneeNode); InvBind = LeftKneeNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftKnee, InvBind); setName(LeftKnee, "Left Knee Joint"); setName(LeftKneeNode, "Left Knee Node"); /*================================================================================================*/ /* Left Foot */ LeftFoot = Joint::create(); //create a joint called LeftFoot TempMat.setTranslate(0.0,-3.0,0.0); LeftFoot->setJointTransformation(TempMat); NodeRecPtr LeftFootNode = makeNodeFor(LeftFoot); LeftKneeNode->addChild(LeftFootNode); InvBind = LeftFootNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftFoot, InvBind); setName(LeftFoot, "Left Foot Joint"); setName(LeftFootNode, "Left Foot Node"); /*================================================================================================*/ /* Left Toes */ LeftToes = Joint::create(); //create a bone called ExampleChildbone TempMat.setTranslate(0.0,0.0,1.0); LeftToes->setJointTransformation(TempMat); NodeRecPtr LeftToesNode = makeNodeFor(LeftToes); LeftFootNode->addChild(LeftToesNode); InvBind = LeftToesNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(LeftToes, InvBind); setName(LeftToes, "Left Toes Joint"); setName(LeftToesNode, "Left Toes Node"); /*================================================================================================*/ /* Right Hip */ RightHip = Joint::create(); //create a joint called RightHip TempMat.setTranslate(-1.0,-1.0,0.0); RightHip->setJointTransformation(TempMat); NodeRecPtr RightHipNode = makeNodeFor(RightHip); PelvisNode->addChild(RightHipNode); InvBind = RightHipNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightHip, InvBind); setName(RightHip, "Right Hip Joint"); setName(RightHipNode, "Right Hip Node"); /*================================================================================================*/ /* Right Knee */ RightKnee = Joint::create(); //create a joint called RightKnee TempMat.setTranslate(0.0,-3.0,0.0); RightKnee->setJointTransformation(TempMat); NodeRecPtr RightKneeNode = makeNodeFor(RightKnee); RightHipNode->addChild(RightKneeNode); InvBind = RightKneeNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightKnee, InvBind); setName(RightKnee, "Right Knee Joint"); setName(RightKneeNode, "Right Knee Node"); /*================================================================================================*/ /* Right Foot */ RightFoot = Joint::create(); //create a joint called RightFoot TempMat.setTranslate(0.0,-3.0,0.0); RightFoot->setJointTransformation(TempMat); NodeRecPtr RightFootNode = makeNodeFor(RightFoot); RightKneeNode->addChild(RightFootNode); InvBind = RightFootNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightFoot, InvBind); setName(RightFoot, "Right Foot Joint"); setName(RightFootNode, "Right Foot Node"); /*================================================================================================*/ /* Right Toes */ RightToes = Joint::create(); //create a joint called RightToes TempMat.setTranslate(0.0,0.0,1.0); RightToes->setJointTransformation(TempMat); NodeRecPtr RightToesNode = makeNodeFor(RightToes); RightFootNode->addChild(RightToesNode); InvBind = RightToesNode->getToWorld(); InvBind.invert(); ExampleSkeleton->pushToJoints(RightToes, InvBind); setName(RightToes, "Right Toes Joint"); setName(RightToesNode, "Right Toes Node"); //Create a geometry to attach to the skeleton (i.e-> skin) GeoUInt8PropertyUnrecPtr type = GeoUInt8Property::create(); type->push_back(GL_QUADS); GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create(); lens->push_back(72); GeoPnt3fPropertyUnrecPtr pnts = GeoPnt3fProperty ::create(); // the points of the Quads //Back pnts->push_back(Pnt3f(-0.5, 6.0, 0)); pnts->push_back(Pnt3f( 0.5, 6.0, 0)); pnts->push_back(Pnt3f( 0.5, 12.0, 0)); pnts->push_back(Pnt3f(-0.5, 12.0, 0)); //Head pnts->push_back(Pnt3f(-0.5, 12, 0)); pnts->push_back(Pnt3f( 0.5, 12, 0)); pnts->push_back(Pnt3f( 0.5, 13, 0)); pnts->push_back(Pnt3f(-0.5, 13, 0)); //Left Shoulder pnts->push_back(Pnt3f(0.0, 11.5, 0)); pnts->push_back(Pnt3f(0.0, 12.5, 0)); pnts->push_back(Pnt3f(1.0, 12.0, 0)); pnts->push_back(Pnt3f(1.0, 11.0, 0)); //Left Humerus pnts->push_back(Pnt3f(1.0, 11.0, 0)); pnts->push_back(Pnt3f(1.0, 12.0, 0)); pnts->push_back(Pnt3f(3.0, 12.0, 0)); pnts->push_back(Pnt3f(3.0, 11.0, 0)); //Left Radius pnts->push_back(Pnt3f(3.0, 11.0, 0)); pnts->push_back(Pnt3f(3.0, 12.0, 0)); pnts->push_back(Pnt3f(5.0, 12.0, 0)); pnts->push_back(Pnt3f(5.0, 11.0, 0)); //Left Hand pnts->push_back(Pnt3f(5.0, 11.0, 0)); pnts->push_back(Pnt3f(5.0, 12.0, 0)); pnts->push_back(Pnt3f(6.0, 12.0, 0)); pnts->push_back(Pnt3f(6.0, 11.0, 0)); //Right Shoulder pnts->push_back(Pnt3f(0.0, 11.5, 0)); pnts->push_back(Pnt3f(0.0, 12.5, 0)); pnts->push_back(Pnt3f(-1.0, 12.0, 0)); pnts->push_back(Pnt3f(-1.0, 11.0, 0)); //Right Humerus pnts->push_back(Pnt3f(-1.0, 11.0, 0)); pnts->push_back(Pnt3f(-1.0, 12.0, 0)); pnts->push_back(Pnt3f(-3.0, 12.0, 0)); pnts->push_back(Pnt3f(-3.0, 11.0, 0)); //Right Radius pnts->push_back(Pnt3f(-3.0, 11.0, 0)); pnts->push_back(Pnt3f(-3.0, 12.0, 0)); pnts->push_back(Pnt3f(-5.0, 12.0, 0)); pnts->push_back(Pnt3f(-5.0, 11.0, 0)); //Right Hand pnts->push_back(Pnt3f(-5.0, 11.0, 0)); pnts->push_back(Pnt3f(-5.0, 12.0, 0)); pnts->push_back(Pnt3f(-6.0, 12.0, 0)); pnts->push_back(Pnt3f(-6.0, 11.0, 0)); //Left Hip pnts->push_back(Pnt3f(0.0, 6.5, 0)); pnts->push_back(Pnt3f(0.5, 7.5, 0)); pnts->push_back(Pnt3f( 1.5, 6.0, 0)); pnts->push_back(Pnt3f(0.5, 6.0, 0)); //Left Femur pnts->push_back(Pnt3f(0.5, 6.0, 0)); pnts->push_back(Pnt3f( 1.5, 6.0, 0)); pnts->push_back(Pnt3f( 1.5, 3.0, 0)); pnts->push_back(Pnt3f(0.5, 3.0, 0)); //Left Tibia pnts->push_back(Pnt3f(0.5, 3.0, 0)); pnts->push_back(Pnt3f( 1.5, 3.0, 0)); pnts->push_back(Pnt3f( 1.5, 0.0, 0)); pnts->push_back(Pnt3f(0.5, 0.0, 0)); //Left Foot pnts->push_back(Pnt3f(0.5, 0.0, 0)); pnts->push_back(Pnt3f( 1.5, 0.0, 0)); pnts->push_back(Pnt3f( 1.5, 0.0, 1.0)); pnts->push_back(Pnt3f(0.5, 0.0, 1.0)); //Right Hip pnts->push_back(Pnt3f(0.0, 6.5, 0)); pnts->push_back(Pnt3f(-0.5, 7.5, 0)); pnts->push_back(Pnt3f( -1.5, 6.0, 0)); pnts->push_back(Pnt3f(-0.5, 6.0, 0)); //Right Femur pnts->push_back(Pnt3f(-0.5, 6.0, 0)); pnts->push_back(Pnt3f( -1.5, 6.0, 0)); pnts->push_back(Pnt3f( -1.5, 3.0, 0)); pnts->push_back(Pnt3f(-0.5, 3.0, 0)); //Right Tibia pnts->push_back(Pnt3f(-0.5, 3.0, 0)); pnts->push_back(Pnt3f( -1.5, 3.0, 0)); pnts->push_back(Pnt3f( -1.5, 0.0, 0)); pnts->push_back(Pnt3f(-0.5, 0.0, 0)); //Right Foot pnts->push_back(Pnt3f(-0.5, 0.0, 0)); pnts->push_back(Pnt3f( -1.5, 0.0, 0)); pnts->push_back(Pnt3f( -1.5, 0.0, 1.0)); pnts->push_back(Pnt3f(-0.5, 0.0, 1.0)); //Normals GeoVec3fPropertyUnrecPtr norms = GeoVec3fProperty ::create(); geo=Geometry::create(); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Left Hip norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Left Femur norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Left Tibia norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Left Foot norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); //Right Hip norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Right Femur norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Right Tibia norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); norms->push_back(Vec3f( 0.0,0.0,1.0)); //Right Foot norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); norms->push_back(Vec3f( 0.0,1.0,0.0)); //Tell the geometry (geo) to use the points and normals we just defined geo->setTypes (type); geo->setLengths (lens); geo->setPositions(pnts); geo->setNormals(norms); // assign a material to the geometry to make it visible. The details // of materials are defined later. geo->setMaterial(getDefaultMaterial()); //Create unbound geometry node (for displaying mesh in its bind pose) UnboundGeometry = Node::create(); UnboundGeometry->setCore(geo); UnboundGeometry->setTravMask(0); //By default, we won't show the mesh's bind pose //SkeletonDrawer SkeletonDrawableUnrecPtr ExampleSkeletonDrawable = SkeletonDrawable::create(); ExampleSkeletonDrawable->setSkeleton(ExampleSkeleton); ExampleSkeletonDrawable->setMaterial(ExampleMaterial); ExampleSkeletonDrawable->setDrawBindPose(false); //By default, we don't draw the skeleton's bind pose ExampleSkeletonDrawable->setBindPoseColor(Color4f(0.0, 1.0, 0.0, 1.0)); //When drawn, the skeleton's bind pose renders green ExampleSkeletonDrawable->setDrawPose(true); //By default, we do draw the skeleton's current pose ExampleSkeletonDrawable->setPoseColor(Color4f(0.0, 0.0, 1.0, 1.0)); //The skeleton's current pose renders blue //Skeleton Node SkeletonNode = Node::create(); SkeletonNode->setCore(ExampleSkeletonDrawable); // Skeleton Blended Geometry // Here we are attaching the "skin" to the skeleton so that when the skeleton is animated, the skin moves with it ExampleSkeleton->setBaseGeometry(geo); //Back ExampleSkeleton->addJointBlending(0,Pelvis,1.0f); ExampleSkeleton->addJointBlending(1,Pelvis,1.0f); ExampleSkeleton->addJointBlending(2,Clavicle,1.0f); ExampleSkeleton->addJointBlending(3,Clavicle,1.0f); //Head ExampleSkeleton->addJointBlending(4,Clavicle,1.0f); ExampleSkeleton->addJointBlending(5,Clavicle,1.0f); ExampleSkeleton->addJointBlending(6,Head,1.0f); ExampleSkeleton->addJointBlending(7,Head,1.0f); //Left Shoulder ExampleSkeleton->addJointBlending(8,Clavicle,1.0f); ExampleSkeleton->addJointBlending(9,Clavicle,1.0f); ExampleSkeleton->addJointBlending(10,LeftShoulder,1.0f); ExampleSkeleton->addJointBlending(11,LeftShoulder,1.0f); //Left Humerus ExampleSkeleton->addJointBlending(12,LeftShoulder,1.0f); ExampleSkeleton->addJointBlending(13,LeftShoulder,1.0f); ExampleSkeleton->addJointBlending(14,LeftElbow,0.8f); ExampleSkeleton->addJointBlending(15,LeftElbow,0.8f); ExampleSkeleton->addJointBlending(14,LeftHand,0.2f); ExampleSkeleton->addJointBlending(15,LeftHand,0.2f); //Left Radius ExampleSkeleton->addJointBlending(16,LeftElbow,1.0f); ExampleSkeleton->addJointBlending(17,LeftElbow,1.0f); ExampleSkeleton->addJointBlending(18,LeftHand,1.0f); ExampleSkeleton->addJointBlending(19,LeftHand,1.0f); //Left Hand ExampleSkeleton->addJointBlending(20,LeftHand,1.0f); ExampleSkeleton->addJointBlending(21,LeftHand,1.0f); ExampleSkeleton->addJointBlending(22,LeftFingers,1.0f); ExampleSkeleton->addJointBlending(23,LeftFingers,1.0f); //Right Shoulder ExampleSkeleton->addJointBlending(24,Clavicle,1.0f); ExampleSkeleton->addJointBlending(25,Clavicle,1.0f); ExampleSkeleton->addJointBlending(26,RightShoulder,1.0f); ExampleSkeleton->addJointBlending(27,RightShoulder,1.0f); //Right Humerus ExampleSkeleton->addJointBlending(28,RightShoulder,1.0f); ExampleSkeleton->addJointBlending(29,RightShoulder,1.0f); ExampleSkeleton->addJointBlending(30,RightElbow,1.0f); ExampleSkeleton->addJointBlending(31,RightElbow,1.0f); //Right Radius ExampleSkeleton->addJointBlending(32,RightElbow,1.0f); ExampleSkeleton->addJointBlending(33,RightElbow,1.0f); ExampleSkeleton->addJointBlending(34,RightHand,1.0f); ExampleSkeleton->addJointBlending(35,RightHand,1.0f); //Right Hand ExampleSkeleton->addJointBlending(36,RightHand,1.0f); ExampleSkeleton->addJointBlending(37,RightHand,1.0f); ExampleSkeleton->addJointBlending(38,RightFingers,1.0f); ExampleSkeleton->addJointBlending(39,RightFingers,1.0f); //Left Hip ExampleSkeleton->addJointBlending(40,Pelvis,1.0f); ExampleSkeleton->addJointBlending(41,Pelvis,1.0f); ExampleSkeleton->addJointBlending(42,LeftHip,1.0f); ExampleSkeleton->addJointBlending(43,LeftHip,1.0f); //Left Femur ExampleSkeleton->addJointBlending(44,LeftHip,1.0f); ExampleSkeleton->addJointBlending(45,LeftHip,1.0f); ExampleSkeleton->addJointBlending(46,LeftKnee,1.0f); ExampleSkeleton->addJointBlending(47,LeftKnee,1.0f); //Left Tibia ExampleSkeleton->addJointBlending(48,LeftKnee,1.0f); ExampleSkeleton->addJointBlending(49,LeftKnee,1.0f); ExampleSkeleton->addJointBlending(50,LeftFoot,1.0f); ExampleSkeleton->addJointBlending(51,LeftFoot,1.0f); //Left Foot ExampleSkeleton->addJointBlending(52,LeftFoot,1.0f); ExampleSkeleton->addJointBlending(53,LeftFoot,1.0f); ExampleSkeleton->addJointBlending(54,LeftToes,1.0f); ExampleSkeleton->addJointBlending(55,LeftToes,1.0f); //Right Hip ExampleSkeleton->addJointBlending(56,Pelvis,1.0f); ExampleSkeleton->addJointBlending(57,Pelvis,1.0f); ExampleSkeleton->addJointBlending(58,RightHip,1.0f); ExampleSkeleton->addJointBlending(59,RightHip,1.0f); //Right Femur ExampleSkeleton->addJointBlending(60,RightHip,1.0f); ExampleSkeleton->addJointBlending(61,RightHip,1.0f); ExampleSkeleton->addJointBlending(62,RightKnee,1.0f); ExampleSkeleton->addJointBlending(63,RightKnee,1.0f); //Right Tibia ExampleSkeleton->addJointBlending(64,RightKnee,1.0f); ExampleSkeleton->addJointBlending(65,RightKnee,1.0f); ExampleSkeleton->addJointBlending(66,RightFoot,1.0f); ExampleSkeleton->addJointBlending(67,RightFoot,1.0f); //Right Foot ExampleSkeleton->addJointBlending(68,RightFoot,1.0f); ExampleSkeleton->addJointBlending(69,RightFoot,1.0f); ExampleSkeleton->addJointBlending(70,RightToes,1.0f); ExampleSkeleton->addJointBlending(71,RightToes,1.0f); MeshNode = Node::create(); MeshNode->setCore(ExampleSkeleton); //Create scene node NodeUnrecPtr scene = Node::create(); scene->setCore(Group::create()); scene->addChild(UnboundGeometry); scene->addChild(SkeletonNode); scene->addChild(MeshNode); mgr->setRoot(scene); //Setup the Animation setupAnimation(); //Save to an xml file FCFileType::FCPtrStore Containers; Containers.insert(ExampleSkeleton); Containers.insert(PelvisNode); Containers.insert(TheSkeletonAnimation); //Use an empty Ignore types vector FCFileType::FCTypeVector IgnoreTypes; //IgnoreTypes.push_back(Node::getClassType().getId()); //Write the Field Containers to a xml file FCFileHandler::the()->write(Containers,BoostPath("./13Output.xml"),IgnoreTypes); // Show the whole Scene mgr->showAll(); //Open Window Vec2f WinSize(TutorialWindow->getDesktopSize() * 0.85f); Pnt2f WinPos((TutorialWindow->getDesktopSize() - WinSize) *0.5); TutorialWindow->openWindow(WinPos, WinSize, "13MeshBlending"); //Main Loop TutorialWindow->mainLoop(); osgExit(); return 0; }
void OgreMeshReader::constructSubMesh(SubMeshInfo &smInfo, VertexElementStore &vertexElements) { OSG_OGRE_LOG(("OgreMeshReader::constructSubMesh: meshName '%s'" "matName '%s'\n", smInfo.name.c_str(), smInfo.matName.c_str())); if(smInfo.skelAnim == true) { smInfo.mesh = SkinnedGeometry::create(); } else { smInfo.mesh = Geometry::create(); } smInfo.meshN = makeNodeFor(smInfo.mesh); smInfo.meshN->editSFVolume()->setValue(_rootN->getVolume()); setName(smInfo.meshN, smInfo.name); UInt16 nextIdx = Geometry::TexCoordsIndex; for(UInt32 i = 0; i < vertexElements.size(); ++i) { Int32 usage = -1; Int16 propSlot = -1; switch(vertexElements[i].semantic) { case VES_POSITION: usage = GeoProperty::UsageObjectSpace; propSlot = Geometry::PositionsIndex; break; case VES_BLEND_WEIGHTS: case VES_BLEND_INDICES: case VES_TEXTURE_COORDINATES: usage = GeoProperty::UsageParameterSpace; propSlot = nextIdx++; break; case VES_BINORMAL: case VES_TANGENT: usage = GeoProperty::UsageTangentSpace; propSlot = nextIdx++; break; case VES_NORMAL: usage = GeoProperty::UsageTangentSpace; propSlot = Geometry::NormalsIndex; break; case VES_DIFFUSE: usage = GeoProperty::UsageColorSpace; propSlot = Geometry::ColorsIndex; break; case VES_SPECULAR: usage = GeoProperty::UsageColorSpace; propSlot = Geometry::SecondaryColorsIndex; break; } if(usage >= 0) { vertexElements[i].prop->setUsage(usage); } if(propSlot >= 0) { OSG_OGRE_LOG(("OgreMeshReader::constructSubMesh: vertex elem semantic '%s'" " using property '%u'\n", getVertexElementSemanticString(vertexElements[i].semantic).c_str(), propSlot)); smInfo.mesh->setProperty(vertexElements[i].prop, propSlot); smInfo.mesh->setIndex (smInfo.propIdx, propSlot); } else { SWARNING << "OgreMeshReader::constructSubMesh: no property slot found for " << "vertex elem semantic '" << getVertexElementSemanticString(vertexElements[i].semantic) << "'. Skipping." << std::endl; } if(vertexElements[i].semantic == VES_BLEND_INDICES) { SkinnedGeometry* skin = dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh); skin->setJointIndexProperty(propSlot); } if(vertexElements[i].semantic == VES_BLEND_WEIGHTS) { SkinnedGeometry* skin = dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh); skin->setJointWeightProperty(propSlot); } } GeoUInt8PropertyUnrecPtr types = GeoUInt8Property::create(); switch(smInfo.meshOp) { case SMO_POINT_LIST: types->addValue(GL_POINTS); break; case SMO_LINE_LIST: types->addValue(GL_LINES); break; case SMO_LINE_STRIP: types->addValue(GL_LINE_STRIP); break; case SMO_TRIANGLE_LIST: types->addValue(GL_TRIANGLES); break; case SMO_TRIANGLE_STRIP: types->addValue(GL_TRIANGLE_STRIP); break; case SMO_TRIANGLE_FAN: types->addValue(GL_TRIANGLE_FAN); break; } GeoUInt32PropertyUnrecPtr lengths = GeoUInt32Property::create(); lengths->addValue(smInfo.propIdx->size()); smInfo.mesh->setTypes (types); smInfo.mesh->setLengths(lengths); constructMaterial(smInfo); if(smInfo.skelAnim == true && _skel != NULL) { SkinnedGeometry* skin = dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh); if(skin != NULL) { skin->setSkeleton (_skel); skin->setRenderMode(SkinnedGeometry::RMSkeleton); } } _rootN->addChild(smInfo.meshN); }
//---------------------------------------------------------------------- // Fills a geometry with a new text // Author: afischle, pdaehne //---------------------------------------------------------------------- void TextVectorFace::fillGeo(Geometry *geoPtr, const TextLayoutResult &layoutResult, Real32 scale, Real32 depth, UInt32 level, Real32 creaseAngle) { // cast the field containers down to the needed type and create them // when they have the wrong type GeoPnt3fPropertyUnrecPtr posPtr = dynamic_cast<GeoPnt3fProperty *>(geoPtr->getPositions()); if (posPtr == NULL) { posPtr = GeoPnt3fProperty::create(); geoPtr->setPositions(posPtr); } else posPtr->clear(); GeoVec3fPropertyUnrecPtr normalsPtr = dynamic_cast<GeoVec3fProperty *>(geoPtr->getNormals()); if (normalsPtr == NULL) { normalsPtr = GeoVec3fProperty::create(); geoPtr->setNormals(normalsPtr); } else normalsPtr->clear(); GeoVec2fPropertyUnrecPtr texPtr = dynamic_cast<GeoVec2fProperty *>(geoPtr->getTexCoords()); if (texPtr == NULL) { texPtr = GeoVec2fProperty::create(); geoPtr->setTexCoords(texPtr); } else texPtr->clear(); GeoUInt32PropertyUnrecPtr lensPtr = dynamic_cast<GeoUInt32Property *>(geoPtr->getLengths()); if (lensPtr == NULL) { lensPtr = GeoUInt32Property::create(); geoPtr->setLengths(lensPtr); } else lensPtr->clear(); GeoUInt32PropertyUnrecPtr posIndicesPtr = dynamic_cast<GeoUInt32Property *>( geoPtr->getIndex(Geometry::PositionsIndex)); if (posIndicesPtr == NULL) { posIndicesPtr = GeoUInt32Property::create(); geoPtr->setIndex(posIndicesPtr, Geometry::PositionsIndex); } else posIndicesPtr->clear(); GeoUInt32PropertyUnrecPtr normalIndicesPtr = dynamic_cast<GeoUInt32Property *>( geoPtr->getIndex(Geometry::NormalsIndex)); if (normalIndicesPtr == NULL) { normalIndicesPtr = GeoUInt32Property::create(); geoPtr->setIndex(normalIndicesPtr, Geometry::NormalsIndex); } else normalIndicesPtr->clear(); GeoUInt32PropertyUnrecPtr texCoordIndicesPtr = dynamic_cast<GeoUInt32Property *>( geoPtr->getIndex(Geometry::TexCoordsIndex)); if (texCoordIndicesPtr == NULL) { texCoordIndicesPtr = GeoUInt32Property::create(); geoPtr->setIndex(texCoordIndicesPtr, Geometry::TexCoordsIndex); } else texCoordIndicesPtr->clear(); GeoUInt8PropertyUnrecPtr typesPtr = dynamic_cast<GeoUInt8Property *>(geoPtr->getTypes()); if (typesPtr == NULL) { typesPtr = GeoUInt8Property::create(); geoPtr->setTypes(typesPtr); } else typesPtr->clear(); geoPtr->setColors(NULL); geoPtr->setSecondaryColors(NULL); geoPtr->setTexCoords1(NULL); geoPtr->setTexCoords2(NULL); geoPtr->setTexCoords3(NULL); UInt32 numGlyphs = layoutResult.getNumGlyphs(); if (numGlyphs == 0) { return; } // the interleaved multi-index blocks have the layout // Position | Normal | TexCoord /* geoPtr->getIndexMapping().push_back(Geometry::MapPosition); geoPtr->getIndexMapping().push_back(Geometry::MapNormal); geoPtr->getIndexMapping().push_back(Geometry::MapTexCoords); */ // store the normal for the front face normalsPtr->push_back(Vec3f(0.f, 0.f, 1.f)); if (depth > 0.f) // store the normal for the back face normalsPtr->push_back(Vec3f(0.f, 0.f, -1.f)); UInt32 i; for (i = 0; i < numGlyphs; ++i) { const TextVectorGlyph &glyph = getVectorGlyph(layoutResult.indices[i]); const TextVectorGlyph::PolygonOutline &outline = glyph.getLines(level); const Vec2f &pos = layoutResult.positions[i]; // add the front face to the geometry // store positions and texture coordinates UInt32 coordOffset = posPtr->size(); UInt32 texCoordOffset = texPtr->size(); Real32 coordZ = 0.5f * depth; vector<Vec2f>::const_iterator cIt; for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt) { Vec2f coord = *cIt + pos; Vec2f texCoord = coord; coord *= scale; posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ)); texCoord -= layoutResult.positions.front(); texPtr->push_back(texCoord); } // Store types, lengths and indices vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt; UInt32 indexBegin = 0, indexEnd; for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt) { typesPtr->push_back(tIt->first); indexEnd = tIt->second; OSG_ASSERT(indexEnd >= indexBegin); lensPtr->push_back(indexEnd - indexBegin); UInt32 i; for (i = indexBegin; i < indexEnd; ++i) { // the interleaved multi-index blocks have the layout // Position | Normal | TexCoord OSG_ASSERT(i < outline.indices.size()); UInt32 index = outline.indices[i]; OSG_ASSERT(coordOffset + index < posPtr->size()); posIndicesPtr->push_back(coordOffset + index); normalIndicesPtr->push_back(0); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); } indexBegin = indexEnd; } // add the back and side faces only if depth > 0 if (depth > 0.f) { // add the back face to the geometry // store positions // No need to store texture coordinates - we reuse the // texture coordinates from the front side UInt32 backCoordOffset = posPtr->size(); coordZ = -0.5f * depth; for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt) { Vec2f coord = *cIt + pos; coord *= scale; posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ)); } // Store types, lengths and indices // We have to flip all triangles to enable correct backface culling. // For GL_TRIANGLES, we simply flip the vertices. // For GL_TRIANGLE_FANs, we leave the first vertex at its place and flip the // remaining vertices. // For GL_TRIANGLE_STRIPs, things are more complicated. When the number of // vertices is uneven, we simply flip the vertices. When the number of // vertices is even, we have to add an additional vertex before we flip the // vertices. vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt; UInt32 indexBegin = 0, indexEnd; for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt) { typesPtr->push_back(tIt->first); indexEnd = tIt->second; OSG_ASSERT(indexEnd >= indexBegin); UInt32 len = indexEnd - indexBegin; UInt32 i = indexEnd; if (tIt->first == GL_TRIANGLE_FAN) { i = indexBegin; ++indexBegin; } if ((tIt->first == GL_TRIANGLE_STRIP) && ((len & 1) == 0)) { OSG_ASSERT((indexEnd >= 2) && (indexEnd - 2 >= indexBegin)); i = indexEnd - 2; ++len; } if (i != indexEnd) { // the interleaved multi-index blocks have the layout // Position | Normal | TexCoord OSG_ASSERT(i < outline.indices.size()); UInt32 index = outline.indices[i]; OSG_ASSERT(backCoordOffset + index < posPtr->size()); posIndicesPtr->push_back(backCoordOffset + index); normalIndicesPtr->push_back(1); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); i = indexEnd; } lensPtr->push_back(len); while (true) { if (i <= indexBegin) break; --i; // the interleaved multi-index blocks have the layout // Position | Normal | TexCoord OSG_ASSERT(i < outline.indices.size()); UInt32 index = outline.indices[i]; OSG_ASSERT(backCoordOffset + index < posPtr->size()); posIndicesPtr->push_back(backCoordOffset + index); normalIndicesPtr->push_back(1); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); } indexBegin = indexEnd; } // Add the side faces to the geometry const TextVectorGlyph::Normals &normals = glyph.getNormals(level); // construct the multi index UInt32 start = 0, end, index = 0; vector<UInt32>::const_iterator iIt; vector<TextVectorGlyph::Orientation>::const_iterator oriIt = glyph.getContourOrientations().begin(); for (iIt = outline.contours.begin(); iIt != outline.contours.end(); ++iIt, ++oriIt) { OSG_ASSERT(oriIt != glyph.getContourOrientations().end()); UInt32 contourCoordOffset, contourBackCoordOffset; if (*oriIt == TextVectorGlyph::CCW) { contourCoordOffset = coordOffset; contourBackCoordOffset = backCoordOffset; } else { contourCoordOffset = backCoordOffset; contourBackCoordOffset = coordOffset; } end = *iIt; // the side faces are stored as quads GLenum mode = GL_QUAD_STRIP; UInt32 len = 0; UInt32 coordIndex, backCoordIndex; UInt32 normalOffset, startNormalOffset = normalsPtr->size(); for (index = start; index < end; ++index) { normalOffset = normalsPtr->size() - 1; OSG_ASSERT(index < normals.size()); if (normals[index].edgeAngle > creaseAngle) { // We have an edge with two normals, so we need to // add the vertices twice, but with different normals // - but only when this is not the start index if (index > start) { if ((mode == GL_QUAD_STRIP) && (len > 2)) { typesPtr->push_back(GL_QUAD_STRIP); OSG_ASSERT(((len + 2) & 1) == 0); lensPtr->push_back(len + 2); len = 0; coordIndex = contourCoordOffset + index; backCoordIndex = contourBackCoordOffset + index; } else { mode = GL_QUADS; len += 2; coordIndex = contourBackCoordOffset + index; backCoordIndex = contourCoordOffset + index; } // back OSG_ASSERT(backCoordIndex < posPtr->size()); posIndicesPtr->push_back(backCoordIndex); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); // front OSG_ASSERT(coordIndex < posPtr->size()); posIndicesPtr->push_back(coordIndex); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); } const Vec2f &normal = normals[index].nextEdgeNormal; normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f)); } else { if (mode == GL_QUADS) { typesPtr->push_back(GL_QUADS); mode = GL_QUAD_STRIP; OSG_ASSERT(len >= 6); OSG_ASSERT(((len - 2) & 3) == 0); lensPtr->push_back(len - 2); len = 2; } const Vec2f &normal = normals[index].meanEdgeNormal; normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f)); } ++normalOffset; // back OSG_ASSERT(contourBackCoordOffset + index < posPtr->size()); posIndicesPtr->push_back(contourBackCoordOffset + index); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); // front OSG_ASSERT(contourCoordOffset + index < posPtr->size()); posIndicesPtr->push_back(contourCoordOffset + index); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + index < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + index); len += 2; } // We have to close the strip, so add the start vertices again if (normals[start].edgeAngle <= creaseAngle) normalOffset = startNormalOffset; if (mode == GL_QUAD_STRIP) { coordIndex = contourCoordOffset + start; backCoordIndex = contourBackCoordOffset + start; } else { coordIndex = contourBackCoordOffset + start; backCoordIndex = contourCoordOffset + start; } // back OSG_ASSERT(backCoordIndex < posPtr->size()); posIndicesPtr->push_back(backCoordIndex); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + start < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + start); // front OSG_ASSERT(coordIndex < posPtr->size()); posIndicesPtr->push_back(coordIndex); OSG_ASSERT(normalOffset < normalsPtr->size()); normalIndicesPtr->push_back(normalOffset); OSG_ASSERT(texCoordOffset + start < texPtr->size()); texCoordIndicesPtr->push_back(texCoordOffset + start); len += 2; // store the number of multi index blocks typesPtr->push_back(mode); OSG_ASSERT((mode != GL_QUADS) || ((len & 3) == 0)); OSG_ASSERT((mode != GL_QUAD_STRIP) || ((len & 1) == 0)); lensPtr->push_back(len); start = end; } } } }