void StaticWorldObject::WalkTree(ssgEntity *e, sgVec3 initialpos) { if (!e) return; if (e->isAKindOf (ssgTypeBranch()) ) { ssgBranch *branch = (ssgBranch*) e ; for (int i=0; i<branch->getNumKids(); i++) { ssgEntity *kid = branch->getKid(i); assert(kid!=NULL); WalkTree(kid, initialpos); } } if ( e->isAKindOf ( ssgTypeLeaf () ) ) { AddLeaf((ssgLeaf*)e, initialpos); } }
void updt_bbox(ssgEntity *start, sgVec3 min, sgVec3 max) { int i, j, k; float *vert; for (i = start->getNumKids() - 1; i >= 0; i--) { ssgEntity *e = ((ssgBranch*)start)->getKid(i); if (e->getNumKids() != 0) { updt_bbox(e, min, max); } else { if (e->isAKindOf(ssgTypeLeaf())) { int nbvert = ((ssgLeaf*)e)->getNumVertices(); for (j = 0; j < nbvert; j++) { vert = ((ssgLeaf*)e)->getVertex(j); for (k = 0; k < 3; k++) { if (vert[k] < min[k]) min[k] = vert[k]; if (vert[k] > max[k]) max[k] = vert[k]; } } } } } }
/** * Recursively walk a scene graph and evaluate any node * attributes placed inside the name strings of leaves. * */ void ModelBasedScenery::evaluateNodeAttributes(ssgEntity* ent) { if (ent->isAKindOf(ssgTypeLeaf())) { SSGUtil::NodeAttributes attr = SSGUtil::getNodeAttributes(ent); std::string node_name = SSGUtil::getPureNodeName(ent); if (attr.checkAttribute("terrain") == -1) { ent->clrTraversalMaskBits(SSGTRAV_HOT | SSGTRAV_LOS); std::cout << " leaf \"" << node_name << "\" is excluded from terrain calculations (found -terrain attribute)" << std::endl; } if (attr.checkAttribute("visible") == -1) { std::cout << " leaf \"" << node_name << "\" is invisible (found -visible attribute)" << std::endl; SSGUtil::spliceBranch(new ssgInvisible(), ent); } } else if (ent->isAKindOf(ssgTypeBranch())) { ssgBranch *branch = (ssgBranch*)ent; // continue down the hierarchy int kids = branch->getNumKids(); for (int i = 0; i < kids; i++) { ssgEntity* currKid = branch->getKid(i); evaluateNodeAttributes(currKid); } } }
void ModelBasedScenery::setToInvisibleState(ssgEntity* ent) { if (ent->isAKindOf(ssgTypeLeaf())) { ssgLeaf *leaf = (ssgLeaf*)ent; if (leaf->hasState()) { leaf->setState(invisible_state); } } else if (ent->isAKindOf(ssgTypeBranch())) { ssgBranch *branch = (ssgBranch*)ent; // continue down the hierarchy int kids = branch->getNumKids(); for (int i = 0; i < kids; i++) { ssgEntity* currKid = branch->getKid(i); setToInvisibleState(currKid); } } }
/** * \brief Tile the terrain * * This function recursively walks the scene graph and sorts all * triangles into a grid of smaller graphs. This reduces the * calculation effort: If the position of the plane and therefore * the grid below it is known, only a small fraction of all * triangles has to be tested. * * During the recursive walk down the tree, the function tracks * all transformations. If a leaf node is encountered, the contained * triangles are transformed by the tracked transformations to * get the absolute position of each triangle. Then all triangles * are sorted into the grid by their absolute position. * * \param e Pointer to the currently processed entity * \param xform Reference to the current transformation */ void HD_TilingTerrain::tiling_terrain(ssgEntity * e, sgMat4 xform) { // only continue if HOT traversal is enabled for this entity if ( e->getTraversalMask() & SSGTRAV_HOT ) { if ( e->isAKindOf(ssgTypeBranch()) ) { ssgBranch *br = (ssgBranch *) e ; if ( e -> isA ( ssgTypeTransform() ) ) { sgMat4 xform1; ((ssgTransform *)e)->getTransform ( xform1 ) ; sgPreMultMat4 ( xform, xform1 ) ;//Pre or Post ??? /* std::cout << "------tranform " << br<< std::endl; std::cout << "-------------- " << xform[0][0]<<" "<< xform[0][1]<<" "<< xform[0][2]<<" "<< xform[0][3]<< std::endl; std::cout << "-------------- " << xform[1][0]<<" "<< xform[1][1]<<" "<< xform[1][2]<<" "<< xform[1][3]<< std::endl; std::cout << "-------------- " << xform[2][0]<<" "<< xform[2][1]<<" "<< xform[2][2]<<" "<< xform[2][3]<< std::endl; std::cout << "-------------- " << xform[3][0]<<" "<< xform[3][1]<<" "<< xform[3][2]<<" "<< xform[3][3]<< std::endl; */ } //else std::cout << "------branch " << br<< std::endl; // Bug #16552: "xform" is actually passed by reference and // not by value. Therefore we have to store it locally and // restore it before recursing to the next child. Else all // children receive an xform matrix that was modified by // the previous child. sgMat4 local_xform; sgCopyMat4(local_xform, xform); for ( int i = 0 ; i < br -> getNumKids () ; i++ ) { tiling_terrain ( br -> getKid ( i ), xform); // restore transformation matrix sgCopyMat4(xform, local_xform); } } else if ( e -> isAKindOf ( ssgTypeLeaf() ) ) { //std::cout << "------leaf " << e<< std::endl; ssgLeaf *leaf = (ssgLeaf *) e ; int nt = leaf->getNumTriangles(); //std::cout << "------n triangles " << nt<< std::endl; for ( int i = 0 ; i < nt ; i++ )//pour chaque triangle { short iv1,iv2,iv3;/*float *v1, *v2, *v3;*/ sgVec3 v1,v2,v3; leaf->getTriangle ( i, &iv1, &iv2, &iv3 ); sgCopyVec3 (v1 , leaf->getVertex(iv1)); sgXformPnt3( v1, xform); sgCopyVec3 (v2 , leaf->getVertex(iv2)); sgXformPnt3( v2, xform); sgCopyVec3 (v3 , leaf->getVertex(iv3)); sgXformPnt3( v3, xform); /* std::cout << "------triangle " << std::endl; std::cout << "-------------- " << v1[0]<<" "<< v1[1]<<" "<< v1[2]<<" "<< std::endl; std::cout << "-------------- " << v2[0]<<" "<< v2[1]<<" "<< v2[2]<<" "<< std::endl; std::cout << "-------------- " << v3[0]<<" "<< v3[1]<<" "<< v3[2]<<" "<< std::endl; */ //calcule cube englobant sgBox box; box.empty(); box.extend(v1); box.extend(v2); box.extend(v3); //std::cout << "Min " << box.min[0]<<", "<<box.min[1]<<", "<<box.min[2]<<" Max"<<box.max[0]<<", "<<box.max[1]<<", "<<box.max[2]<< std::endl; //ajoute dans cellules recouvertes int save = 1; int i1 = (int)(-0.1+box.min[0]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2; int i2 = (int)(0.1+box.max[0]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2; int j1 = (int)(-0.1+box.min[2]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2; int j2 = (int)(0.1+box.max[2]/SIZE_CELL_GRID_PLANES) + SIZE_GRID_PLANES/2; if (((i1<0) && (i2<0)) ||((i1>SIZE_GRID_PLANES) && (i2>SIZE_GRID_PLANES)) ) { save = 0; } if (((j1<0) && (j2<0)) ||((j1>SIZE_GRID_PLANES) && (j2>SIZE_GRID_PLANES)) ) { save = 0; } if (i1<0) i1=0; if (i1>SIZE_GRID_PLANES) i1 = SIZE_GRID_PLANES; if (i2<0) i2=0; if (i2>SIZE_GRID_PLANES) i2 = SIZE_GRID_PLANES; if (j1<0) j1=0; if (j1>SIZE_GRID_PLANES) j1 = SIZE_GRID_PLANES; if (j2<0) j2=0; if (j2>SIZE_GRID_PLANES) j2 = SIZE_GRID_PLANES; //std::cout << "cellules i, j " << i1 <<", "<<i2<<", "<<j1<<","<<j2<< std::endl; if (save) { for ( int i = i1 ; i <= i2; i++ ) { for ( int j = j1 ; j <= j2; j++ ) { //std::cout << "met dans cellule " << i <<", "<<j<< std::endl; tile_table[i][j]->add(v1); tile_table[i][j]->add(v2); tile_table[i][j]->add(v3); } } } } } } }
/** \brief Create a "shadow" instance of a model * * This function operates on a clone of a model and sets all associated * states to a "shadowy" look. If it is called for an entity that has the * "-shadow" attribute set, return true to signal the caller that he has to * remove this entity from the graph. * * \todo If the video context supports stencil buffering, the shadow * should be rendered using the stencil buffer to get a translucent look. * * \param ent A clone of the "real" model * \retval true The current entity has to be removed from the graph * \retval false No action required */ bool makeShadow(ssgEntity *ent) { bool boRemoveCurrentEntity = false; if (ent->isAKindOf(ssgTypeLeaf())) { ssgLeaf *leaf = (ssgLeaf*)ent; SSGUtil::NodeAttributes attr = SSGUtil::getNodeAttributes(leaf); if (!attr.castsShadow) { // no shadow --> remove this entity from all parents boRemoveCurrentEntity = true; } else if (leaf->hasState()) { ssgSimpleState *state = (ssgSimpleState*)leaf->getState(); state->disable(GL_COLOR_MATERIAL); state->disable(GL_TEXTURE_2D); state->enable(GL_LIGHTING); state->enable(GL_BLEND); state->setShadeModel(GL_SMOOTH); state->setShininess(0.0f); state->setMaterial(GL_EMISSION, 0.0, 0.0, 0.0, 0.0); #ifdef EXPERIMENTAL_STENCIL_SHADOW if (vidbits.stencil) { state->setMaterial(GL_AMBIENT, 0.0, 0.0, 0.0, 0.1); state->setMaterial(GL_DIFFUSE, 0.0, 0.0, 0.0, 0.1); state->setMaterial(GL_SPECULAR, 0.0, 0.0, 0.0, 0.1); state->setStateCallback(SSG_CALLBACK_PREDRAW, shadowPredrawCallback); state->setStateCallback(SSG_CALLBACK_POSTDRAW, shadowPostdrawCallback); } else #endif { state->setMaterial(GL_AMBIENT, 0.0, 0.0, 0.0, 1.0); state->setMaterial(GL_DIFFUSE, 0.0, 0.0, 0.0, 1.0); state->setMaterial(GL_SPECULAR, 0.0, 0.0, 0.0, 1.0); state->setStateCallback(SSG_CALLBACK_PREDRAW, NULL); state->setStateCallback(SSG_CALLBACK_POSTDRAW, NULL); } } } else if (ent->isAKindOf(ssgTypeBranch())) { ssgBranch *branch = (ssgBranch*)ent; // continue down the hierarchy std::list<ssgLeaf*> ToBeRemoved; std::list<ssgLeaf*>::iterator it; int kids = branch->getNumKids(); for (int i = 0; i < kids; i++) { ssgEntity* currKid = branch->getKid(i); if (makeShadow(currKid)) { ToBeRemoved.push_back(static_cast<ssgLeaf*>(currKid)); } } for (it = ToBeRemoved.begin(); it != ToBeRemoved.end(); it++) { SSGUtil::removeLeafFromGraph(*it); } } return boRemoveCurrentEntity; }