// Initialize GLUT & OpenSG and set up the scene int main(int argc, char **argv) { // OSG init osgInit(argc,argv); // GLUT init int winid = setupGLUT(&argc, argv); // the connection between GLUT and OpenSG GLUTWindowPtr gwin= GLUTWindow::create(); gwin->setId(winid); gwin->init(); // create the scene /* In the previous example, the colors and positions used the same indices. That might not always be the preferred way, and it might not make sense for other properties, e.g. normals. It is possible to assign a different index for every property. See the indices section below for details. */ /* The initial setup is the same as in the single indexed geometry... */ GeoPTypesPtr type = GeoPTypesUI8::create(); beginEditCP(type, GeoPTypesUI8::GeoPropDataFieldMask); { type->push_back(GL_POLYGON ); type->push_back(GL_TRIANGLES); type->push_back(GL_QUADS ); } endEditCP (type, GeoPTypesUI8::GeoPropDataFieldMask); GeoPLengthsPtr lens = GeoPLengthsUI32::create(); beginEditCP(lens, GeoPLengthsUI32::GeoPropDataFieldMask); { lens->push_back(4); lens->push_back(6); lens->push_back(8); } endEditCP (lens, GeoPLengthsUI32::GeoPropDataFieldMask); GeoPositions3fPtr pnts = GeoPositions3f::create(); beginEditCP(pnts, GeoPositions3f::GeoPropDataFieldMask); { // the base pnts->push_back(Pnt3f(-1, -1, -1)); pnts->push_back(Pnt3f(-1, -1, 1)); pnts->push_back(Pnt3f( 1, -1, 1)); pnts->push_back(Pnt3f( 1, -1, -1)); // the roof base pnts->push_back(Pnt3f(-1, 0, -1)); pnts->push_back(Pnt3f(-1, 0, 1)); pnts->push_back(Pnt3f( 1, 0, 1)); pnts->push_back(Pnt3f( 1, 0, -1)); // the gable pnts->push_back(Pnt3f( 0, 1, -1)); pnts->push_back(Pnt3f( 0, 1, 1)); } endEditCP (pnts, GeoPositions3f::GeoPropDataFieldMask); GeoColors3fPtr colors = GeoColors3f::create(); beginEditCP(colors, GeoColors3f::GeoPropDataFieldMask); { colors->push_back(Color3f(1, 1, 0)); colors->push_back(Color3f(1, 0, 0)); colors->push_back(Color3f(1, 0, 0)); colors->push_back(Color3f(1, 1, 0)); colors->push_back(Color3f(0, 1, 1)); colors->push_back(Color3f(1, 0, 1)); } endEditCP (colors, GeoPositions3f::GeoPropDataFieldMask); /* A new property: normals. They are used for lighting calculations and have to point away from the surface. Normals are standard vectors. */ GeoNormals3fPtr norms = GeoNormals3f::create(); beginEditCP(norms, GeoNormals3f::GeoPropDataFieldMask); { norms->push_back(Vec3f(-1, 0, 0)); norms->push_back(Vec3f( 1, 0, 0)); norms->push_back(Vec3f( 0, -1, 0)); norms->push_back(Vec3f( 0, 1, 0)); norms->push_back(Vec3f( 0, 0, -1)); norms->push_back(Vec3f( 0, 0, 1)); } endEditCP (norms, GeoNormals3f::GeoPropDataFieldMask); /* To use different indices for different attributes they have to be specified. This is done within the single index property, by using more than one index per vertex. In this case every vertex reads multiple indices from the Indices property. The meaning of every index is defined by the indexMapping given below. */ GeoIndicesUI32Ptr indices = GeoIndicesUI32::create(); beginEditCP(indices, GeoIndicesUI32::GeoPropDataFieldMask); { // indices for the polygon indices->push_back(0); // position index indices->push_back(3); // color/normal index indices->push_back(1); // position index indices->push_back(3); // color/normal index indices->push_back(2); // position index indices->push_back(3); // color/normal index indices->push_back(3); // position index indices->push_back(3); // color/normal index // indices for the triangles indices->push_back(7); // position index indices->push_back(4); // color/normal index indices->push_back(4); // position index indices->push_back(4); // color/normal index indices->push_back(8); // position index indices->push_back(4); // color/normal index indices->push_back(5); // position index indices->push_back(5); // color/normal index indices->push_back(6); // position index indices->push_back(5); // color/normal index indices->push_back(9); // position index indices->push_back(5); // color/normal index // indices for the quads indices->push_back(1); // position index indices->push_back(5); // color/normal index indices->push_back(2); // position index indices->push_back(5); // color/normal index indices->push_back(6); // position index indices->push_back(5); // color/normal index indices->push_back(5); // position index indices->push_back(5); // color/normal index indices->push_back(3); // position index indices->push_back(4); // color/normal index indices->push_back(0); // position index indices->push_back(4); // color/normal index indices->push_back(4); // position index indices->push_back(4); // color/normal index indices->push_back(7); // position index indices->push_back(4); // color/normal index } endEditCP (indices, GeoIndicesUI32::GeoPropDataFieldMask); /* Put it all together into a Geometry NodeCore. */ GeometryPtr geo=Geometry::create(); beginEditCP(geo, Geometry::TypesFieldMask | Geometry::LengthsFieldMask | Geometry::IndicesFieldMask | Geometry::IndexMappingFieldMask | Geometry::PositionsFieldMask | Geometry::NormalsFieldMask | Geometry::ColorsFieldMask | Geometry::MaterialFieldMask ); { geo->setTypes (type); geo->setLengths (lens); geo->setIndices (indices); /* The meaning of the different indices is given by the indexMapping field. If contains an entry that defines which index for a vertex selects which attribute. In this example the first index selects the positions, the second is used for colors and normals. The number of elements in the indexMapping field defines the number of indices used for every vertex. */ geo->editMFIndexMapping()->push_back(Geometry::MapPosition ); geo->editMFIndexMapping()->push_back(Geometry::MapColor | Geometry::MapNormal ); geo->setPositions(pnts ); geo->setColors (colors); geo->setNormals (norms ); /* Use a lit material this time, to show the effect of the normals. */ geo->setMaterial (getDefaultMaterial()); } endEditCP (geo, Geometry::TypesFieldMask | Geometry::LengthsFieldMask | Geometry::IndicesFieldMask | Geometry::IndexMappingFieldMask | Geometry::PositionsFieldMask | Geometry::NormalsFieldMask | Geometry::ColorsFieldMask | Geometry::MaterialFieldMask ); // put the geometry core into a node NodePtr n = Node::create(); beginEditCP(n, Node::CoreFieldMask); { n->setCore(geo); } endEditCP (n, Node::CoreFieldMask); // add a transformation to make it move NodePtr scene = Node::create(); trans = Transform::create(); beginEditCP(scene, Node::CoreFieldMask | Node::ChildrenFieldMask ); { scene->setCore(trans); scene->addChild(n); } endEditCP (scene, Node::CoreFieldMask | Node::ChildrenFieldMask ); // create the SimpleSceneManager helper mgr = new SimpleSceneManager; // tell the manager what to manage mgr->setWindow(gwin ); mgr->setRoot (scene); // show the whole scene mgr->showAll(); // GLUT main loop glutMainLoop(); return 0; }
GeometryPtr PerformerLoader::traverseGSet(NodePtr node, pfGeoSet *gset) { FINFO(("PerformerLoader::traverseGSet: traversing %p: ", gset)); if(gset->getType()->isDerivedFrom(pfGeoArray::getClassType())) { return traverseGArray(node, dynamic_cast<pfGeoArray*>(gset)); } pfGeoState *gstate = gset->getGState(); int primtype, primcount, vertcount; primtype = gset->getPrimType(); primcount = gset->getNumPrims(); FINFO(("pt %d, pc %d ", primtype, primcount)); int lencount, *lenlist; if (lenlist = gset->getPrimLengths()) { int i; for (i = 0, lencount = 0; i < primcount; i++) lencount += PF_ABS(lenlist[i]); } // Map Performer to OpenGL primtype UInt32 oprimtype = GL_POINTS; static int pprimtypes[] = { PFGS_POINTS, PFGS_LINES, PFGS_TRIS, PFGS_QUADS, PFGS_LINESTRIPS, PFGS_TRISTRIPS, PFGS_TRIFANS, PFGS_POLYS, PFGS_FLAT_LINESTRIPS, PFGS_FLAT_TRISTRIPS, PFGS_FLAT_TRIFANS, -1}; static int oprimtypes[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_QUADS, GL_LINE_STRIP, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_POLYGON, GL_LINE_STRIP, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN }; for (UInt16 i = 0; pprimtypes[i] != -1; ++i) if(pprimtypes[i] == primtype) oprimtype = oprimtypes[i]; int cn_buffer = 0; switch (primtype) { case PFGS_POINTS: vertcount = primcount; primcount = 1; break; case PFGS_LINES: vertcount = primcount * 2; primcount = 1; break; case PFGS_TRIS: vertcount = primcount * 3; primcount = 1; break; case PFGS_QUADS: vertcount = primcount * 4; primcount = 1; break; case PFGS_LINESTRIPS: case PFGS_TRISTRIPS: case PFGS_TRIFANS: case PFGS_POLYS: vertcount = lencount; break; case PFGS_FLAT_LINESTRIPS: FDEBUG(("PerformerLoader::traverseGSet: found " "primitive PFGS_FLAT_LINESTRIPS, will split into" "individual lines!\n")); cn_buffer = 1; vertcount = lencount; break; case PFGS_FLAT_TRISTRIPS: FDEBUG(("PerformerLoader::traverseGSet: found " "primitive PFGS_FLAT_TRISTRIPS!\n")); cn_buffer = 2; vertcount = lencount; break; case PFGS_FLAT_TRIFANS: FDEBUG(("PerformerLoader::traverseGSet: found " "primitive PFGS_FLAT_TRIFANS!\n")); cn_buffer = 2; vertcount = lencount; break; } FINFO(("vc %d ", vertcount)); // Fill the Geometry GeometryPtr ogeo = Geometry::create(); beginEditCP(ogeo); if(gstate) { ogeo->setMaterial(traverseGState(node, gstate)); } else { ogeo->setMaterial(NullFC); } GeoPTypesPtr otypes = GeoPTypesUI8::create(); beginEditCP(otypes); if (lenlist = gset->getPrimLengths()) { GeoPLengthsUI32Ptr olens = GeoPLengthsUI32::create(); beginEditCP(olens); for (int i = 0; i < primcount; i++) { otypes->push_back(oprimtype); olens->push_back(lenlist[i]); } endEditCP(olens); ogeo->setLengths(olens); } else { otypes->push_back(oprimtype); lenlist = &vertcount; lencount = vertcount; if(primcount != 1) FWARNING(("PerformerLoader::traverseGSet: No lens, but " "primcount=%d.\n", primcount)); } endEditCP(otypes); ogeo->setTypes(otypes); // Convert the geo attributes int pmin, pmax; pfVec3 *pverts; ushort *pinds; GeoPositions3fPtr opos = GeoPositions3f::create(); GeoIndicesUI16Ptr oind = GeoIndicesUI16::create(); beginEditCP(opos); beginEditCP(oind); gset->getAttrLists(PFGS_COORD3, (void**)&pverts, &pinds); if(pverts) { if(pinds) { FINFO(("Vi %d-%d ", pmin, pmax)); gset->getAttrRange(PFGS_COORD3, &pmin, &pmax); for(UInt32 i = 0; i < pmax+1; ++i) opos->push_back(Vec3f(pverts[i].vec)); for(UInt32 i = 0; i < vertcount; ++i) oind->push_back(pinds[i]); } else { FINFO(("V ")); for(UInt32 i = 0; i < vertcount; ++i) opos->push_back(Vec3f(pverts[i].vec)); } } endEditCP(opos); endEditCP(oind); ogeo->setPositions(opos); if(oind->size()) { ogeo->setIndices(oind); } else { subRefCP(oind); } int bind; // Normals if((bind = gset->getAttrBind(PFGS_NORMAL3)) != PFGS_OFF) { if(bind == PFGS_PER_PRIM) { FNOTICE(("PerformerLoader::traverseGSet: found PER_PRIM binding " "for normals, ignoring them.\n")); } else if(bind == PFGS_OVERALL) { FINFO(("NO ")); GeoNormals3fPtr onorm = GeoNormals3f::create(); beginEditCP(onorm); pfVec3 *pnorms; gset->getAttrLists(PFGS_NORMAL3, (void**)&pnorms, &pinds); if(pnorms) { Vec3f c; c.setValues(pnorms[0].vec[0], pnorms[0].vec[1], pnorms[0].vec[2]); #if 0 // This assumes a single normal is used as overall. Not true for 1.x onorm->getField().push_back(c); #else for(int i = 0; i < vertcount; ++i) onorm->getField().push_back(c); #endif } endEditCP(onorm); ogeo->setNormals(onorm); } else { GeoNormals3fPtr onorm = GeoNormals3f::create(); beginEditCP(onorm); pfVec3 *pnorms; ushort *pninds; gset->getAttrLists(PFGS_NORMAL3, (void**)&pnorms, &pninds); if(pnorms) { if(pninds) { int pcmin, pcmax; gset->getAttrRange(PFGS_NORMAL3, &pcmin, &pcmax); FINFO(("NI %d-%d ", pcmin, pcmax)); // Check indices if(pcmax != pmax) FWARNING(("Normal pmax %d != pmax %d!\n", pcmax, pmax)); for(int i = 0; i < pcmax; ++i) { if(pinds[i] != pninds[i]) FWARNING(("Normal Index %d (%d) != vind (%d)!\n", i, pninds[i], pinds[i])); } int ind = 0; for(int j = 0; j < primcount; ++j) { Vec3f c; c.setValues(pnorms[0].vec[0], pnorms[0].vec[1], pnorms[0].vec[2]); for(UInt32 i = 0; i < cn_buffer; ++i) { onorm->getField().push_back(c); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Vec3f c; c.setValues(pnorms[ind].vec[0], pnorms[ind].vec[1], pnorms[ind].vec[2]); onorm->getField().push_back(c); } } } else { FINFO(("N ")); int ind = 0; for(int j = 0; j < primcount; ++j) { Vec3f c; c.setValues(pnorms[0].vec[0], pnorms[0].vec[1], pnorms[0].vec[2]); for(UInt32 i = 0; i < cn_buffer; ++i) { onorm->getField().push_back(c); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Vec3f c; c.setValues(pnorms[ind].vec[0], pnorms[ind].vec[1], pnorms[ind].vec[2]); onorm->getField().push_back(c); } } } } endEditCP(onorm); ogeo->setNormals(onorm); } } // Colors if((bind = gset->getAttrBind(PFGS_COLOR4)) != PFGS_OFF) { if(bind == PFGS_PER_PRIM) { FNOTICE(("PerformerLoader::traverseGSet: found PER_PRIM binding " "for colors, ignoring them.\n")); } else if(bind == PFGS_OVERALL) { FINFO(("CO ")); GeoColors4fPtr ocols = GeoColors4f::create(); beginEditCP(ocols); pfVec4 *pcols; gset->getAttrLists(PFGS_COLOR4, (void**)&pcols, &pinds); if(pcols) { Color4f c; c.setValuesRGBA(pcols[0].vec[0], pcols[0].vec[1], pcols[0].vec[2], pcols[0].vec[3]); #if 0 // This assumes a single colors is used as overall. Not true for 1.x ocols->getField().push_back(c); #else for(int i = 0; i < vertcount; ++i) ocols->getField().push_back(c); #endif } endEditCP(ocols); ogeo->setColors(ocols); } else { GeoColors4fPtr ocols = GeoColors4f::create(); beginEditCP(ocols); pfVec4 *pcols; ushort *pcinds; gset->getAttrLists(PFGS_COLOR4, (void**)&pcols, &pcinds); if(pcols) { if(pcinds) { int pcmin, pcmax; gset->getAttrRange(PFGS_COLOR4, &pcmin, &pcmax); FINFO(("CI %d-%d ", pcmin, pcmax)); if(pcmax != pmax) FWARNING(("Color pmax %d != pmax %d!\n", pcmax, pmax)); for(int i = 0; i < pcmax; ++i) { if(pinds[i] != pcinds[i]) FWARNING(("Color Index %d (%d) != vind (%d)!\n", i, pcinds[i], pinds[i])); } // !!! Indices ignored for now, assumed to be the same // as for positions int ind = 0; for(int j = 0; j < primcount; ++j) { Color4f c; c.setValuesRGBA(pcols[0].vec[0], pcols[0].vec[1], pcols[0].vec[2], pcols[0].vec[3]); for(UInt32 i = 0; i < cn_buffer; ++i) { ocols->getField().push_back(c); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Color4f c; c.setValuesRGBA(pcols[ind].vec[0], pcols[ind].vec[1], pcols[ind].vec[2], pcols[ind].vec[3]); ocols->getField().push_back(c); } } } else { FINFO(("C ")); int ind = 0; for(int j = 0; j < primcount; ++j) { Color4f c; c.setValuesRGBA(pcols[0].vec[0], pcols[0].vec[1], pcols[0].vec[2], pcols[0].vec[3]); for(UInt32 i = 0; i < cn_buffer; ++i) { ocols->getField().push_back(c); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Color4f c; c.setValuesRGBA(pcols[ind].vec[0], pcols[ind].vec[1], pcols[ind].vec[2], pcols[ind].vec[3]); ocols->getField().push_back(c); } } } } endEditCP(ocols); ogeo->setColors(ocols); } } // Texture coordinates if((bind = gset->getAttrBind(PFGS_TEXCOORD2)) != PFGS_OFF) { if(bind == PFGS_PER_PRIM) { FNOTICE(("PerformerLoader::traverseGSet: found PER_PRIM binding " "for texcoords, ignoring them.\n")); } else if(bind == PFGS_OVERALL) { FINFO(("TO ")); GeoTexCoords2fPtr otexc = GeoTexCoords2f::create(); beginEditCP(otexc); pfVec2 *ptexcs; gset->getAttrLists(PFGS_TEXCOORD2, (void**)&ptexcs, &pinds); if(ptexcs) { Vec2f tc; tc.setValues(ptexcs[0].vec[0], ptexcs[0].vec[1]); #if 0 // This assumes a single texcal is used as overall. Not true for 1.x otexc->getField().push_back(tc); #else for(int i = 0; i < vertcount; ++i) otexc->getField().push_back(tc); #endif } endEditCP(otexc); ogeo->setTexCoords(otexc); } else { GeoTexCoords2fPtr otexc = GeoTexCoords2f::create(); beginEditCP(otexc); pfVec2 *ptexcs; ushort *ptexinds; gset->getAttrLists(PFGS_TEXCOORD2, (void**)&ptexcs, &ptexinds); if(ptexcs) { if(ptexinds) { int pcmin, pcmax; gset->getAttrRange(PFGS_TEXCOORD2, &pcmin, &pcmax); FINFO(("TI %d-%d ", pcmin, pcmax)); // Check indices if(pcmax != pmax) FWARNING(("TexCoord pmax %d != pmax %d!\n", pcmax, pmax)); for(int i = 0; i < pcmax; ++i) { if(pinds[i] != ptexinds[i]) FWARNING(("TexCoord Index %d (%d) != vind (%d)!\n", i, ptexinds[i], pinds[i])); } int ind = 0; for(int j = 0; j < primcount; ++j) { Vec2f tc; tc.setValues(ptexcs[0].vec[0], ptexcs[0].vec[1]); for(UInt32 i = 0; i < cn_buffer; ++i) { otexc->getField().push_back(tc); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Vec2f tc; tc.setValues(ptexcs[ind].vec[0], ptexcs[ind].vec[1]); otexc->getField().push_back(tc); } } } else { FINFO(("T ")); int ind = 0; for(int j = 0; j < primcount; ++j) { Vec2f tc; tc.setValues(ptexcs[0].vec[0], ptexcs[0].vec[1]); for(UInt32 i = 0; i < cn_buffer; ++i) { otexc->getField().push_back(tc); } for(UInt32 i = 0; i < lenlist[j] - cn_buffer; ++i, ++ind) { Vec2f tc; tc.setValues(ptexcs[ind].vec[0], ptexcs[ind].vec[1]); otexc->getField().push_back(tc); } } } } endEditCP(otexc); ogeo->setTexCoords(otexc); } } FINFO(("\n")); endEditCP(ogeo); //FINFO(("PerformerLoader::Geo dump %p\n", gset)); //ogeo->dump(); return ogeo; }