/** \brief Perform the basic scenegraph initialization * * Initializes the PLIB SSG library, creates the scenegraph * root, a rendering context and the sun. */ void initialize_scenegraph() { // Initialize SSG ssgInit(); // add to SSG function for read JPEG Textures ::ssgAddTextureFormat ( ".jpg", ssgLoadJPG); // font puSetDefaultFonts ( FONT_HELVETICA_14, FONT_HELVETICA_14 ); // Some basic OpenGL setup sgVec4 skycol; sgSetVec4 ( skycol, 0.0f, 0.0f, 0.0f, 1.0f ) ; glClearColor ( skycol[0], skycol[1], skycol[2], skycol[3] ) ; glEnable ( GL_DEPTH_TEST ) ; // Set up the viewing parameters context = new ssgContext(); context->setFOV ( 35.0f, 0 ) ; context->setNearFar ( 1.0f, 10000.0f ) ; context->makeCurrent(); ssgModelPath(""); ssgTexturePath("textures"); // Create a root node scene = new ssgRoot(); // Set up a light source sgVec4 lightamb; sgSetVec4(lightamb , 0.2f, 0.2f, 0.2f, 1.0f); ssgGetLight(0)->setPosition(lightposn); ssgGetLight(0)->setColour(GL_AMBIENT, lightamb); ssgGetLight(0)->setPosition(lightposn); }
static ssgTransform *initWheel(tCarElt *car, int wheel_index) { int i, j, k; float alpha; sgVec3 vtx; sgVec4 clr; sgVec3 nrm; sgVec2 tex; tdble b_offset = 0.0f; tdble curAngle = 0.0f; #define BRK_BRANCH 16 #define BRK_ANGLE (2.0 * M_PI / (tdble)BRK_BRANCH) #define BRK_OFFSET 0.2 switch(wheel_index) { case FRNT_RGT: curAngle = -(M_PI / 2.0 + BRK_ANGLE); b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0; break; case FRNT_LFT: curAngle = -(M_PI / 2.0 + BRK_ANGLE); b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET; break; case REAR_RGT: curAngle = (M_PI / 2.0 - BRK_ANGLE); b_offset = BRK_OFFSET - car->_tireWidth(wheel_index) / 2.0; break; case REAR_LFT: curAngle = (M_PI / 2.0 - BRK_ANGLE); b_offset = car->_tireWidth(wheel_index) / 2.0 - BRK_OFFSET; break; } /* hub */ ssgVertexArray *brk_vtx = new ssgVertexArray(BRK_BRANCH + 1); ssgColourArray *brk_clr = new ssgColourArray(1); ssgNormalArray *brk_nrm = new ssgNormalArray(1); tdble hubRadius; /* center */ vtx[0] = vtx[2] = 0.0; vtx[1] = b_offset; brk_vtx->add(vtx); hubRadius = car->_brakeDiskRadius(wheel_index) * 0.6; for (i = 0; i < BRK_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = hubRadius * cos(alpha); vtx[1] = b_offset; vtx[2] = hubRadius * sin(alpha); brk_vtx->add(vtx); } clr[0] = clr[1] = clr[2] = 0.0; clr[3] = 1.0; brk_clr->add(clr); nrm[0] = nrm[2] = 0.0; // Make normal point outside to have proper lighting. switch(wheel_index) { case FRNT_RGT: case REAR_RGT: nrm[1] = -1.0; break; case FRNT_LFT: case REAR_LFT: nrm[1] = 1.0; break; } brk_nrm->add(nrm); ssgVtxTable *brk = new ssgVtxTable(GL_TRIANGLE_FAN, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(commonState); ssgTransform *wheel = new ssgTransform; wheel->addKid(brk); /* Brake disk */ brk_vtx = new ssgVertexArray(BRK_BRANCH + 4); brk_clr = new ssgColourArray(1); brk_nrm = new ssgNormalArray(1); for (i = 0; i < (BRK_BRANCH / 2 + 2); i++) { alpha = curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha); vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha); brk_vtx->add(vtx); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6; vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6; brk_vtx->add(vtx); } clr[0] = clr[1] = clr[2] = 0.1; clr[3] = 1.0; brk_clr->add(clr); //nrm[0] = nrm[2] = 0.0; //nrm[1] = 1.0; brk_nrm->add(nrm); brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(brakeState); grCarInfo[grCarIndex].brkColor[wheel_index] = brk_clr; wheel->addKid(brk); /* Brake caliper */ brk_vtx = new ssgVertexArray(BRK_BRANCH - 4); brk_clr = new ssgColourArray(1); brk_nrm = new ssgNormalArray(1); for (i = 0; i < (BRK_BRANCH / 2 - 2); i++) { alpha = - curAngle + (float)i * 2.0 * M_PI / (float)(BRK_BRANCH - 1); vtx[0] = (car->_brakeDiskRadius(wheel_index) + 0.02) * cos(alpha); vtx[1] = b_offset; vtx[2] = (car->_brakeDiskRadius(wheel_index) + 0.02) * sin(alpha); brk_vtx->add(vtx); vtx[0] = car->_brakeDiskRadius(wheel_index) * cos(alpha) * 0.6; vtx[1] = b_offset; vtx[2] = car->_brakeDiskRadius(wheel_index) * sin(alpha) * 0.6; brk_vtx->add(vtx); } clr[0] = 0.2; clr[1] = 0.2; clr[2] = 0.2; clr[3] = 1.0; brk_clr->add(clr); //nrm[0] = nrm[2] = 0.0; //nrm[1] = 1.0; brk_nrm->add(nrm); brk = new ssgVtxTable(GL_TRIANGLE_STRIP, brk_vtx, brk_nrm, NULL, brk_clr); brk->setCullFace(0); brk->setState(commonState); wheel->addKid(brk); DBG_SET_NAME(wheel, "Wheel", grCarIndex, wheel_index); grCarInfo[grCarIndex].wheelPos[wheel_index] = wheel; /* wheels */ ssgTransform *whrotation = new ssgTransform; grCarInfo[grCarIndex].wheelRot[wheel_index] = whrotation; wheel->addKid(whrotation); ssgSelector *whselector = new ssgSelector; whrotation->addKid(whselector); grCarInfo[grCarIndex].wheelselector[wheel_index] = whselector; float wheelRadius = car->_rimRadius(wheel_index) + car->_tireHeight(wheel_index); // Create wheels for 4 speeds (stillstanding - fast --> motion blur, look at the texture). for (j = 0; j < 4; j++) { ssgBranch *whl_branch = new ssgBranch; ssgEntity *whl3d = 0; // load speed-dependant 3D wheels if available and if detailed wheels are desired. // wheel data files are located in the wheels directory. first set directory. if (grUseDetailedWheels == DETAILED) { const int bufsize = 1024; char buf[bufsize]; const char* wheel_dir = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D_DIR, 0); if (wheel_dir != 0) { snprintf(buf, bufsize, "wheels/%s", wheel_dir); ssgModelPath(buf); ssgTexturePath(buf); } // set basename for wheel file 0..3 gets appended const char* wheel_obj = GfParmGetStr(car->_carHandle, SECT_GROBJECTS, PRM_WHEEL_3D, 0); if (wheel_obj != 0 && wheel_dir != 0) { snprintf(buf, bufsize, "%s%d.acc", wheel_obj, j); whl3d = grssgCarLoadAC3D(buf, NULL, car->index); } } // if we have a 3D wheel, use it. otherwise use normal generated wheel... if (whl3d) { // Adapt size of the wheel ssgTransform *whl_size = new ssgTransform; sgMat4 wheelsz; sgSetVec4(wheelsz[0], wheelRadius * 2, SG_ZERO, SG_ZERO, SG_ZERO) ; sgSetVec4(wheelsz[1], SG_ZERO, car->_tireWidth(wheel_index), SG_ZERO, SG_ZERO) ; sgSetVec4(wheelsz[2], SG_ZERO, SG_ZERO, wheelRadius * 2, SG_ZERO) ; sgSetVec4(wheelsz[3], SG_ZERO, SG_ZERO, SG_ZERO, SG_ONE) ; whl_size->setTransform(wheelsz); whl_size->addKid(whl3d); whl3d = whl_size; if (wheel_index == FRNT_RGT || wheel_index == REAR_RGT) { // flip wheel around so it faces the right way ssgTransform *whl_mesh_transform = new ssgTransform; sgCoord wheelpos; sgSetCoord(&wheelpos, 0, 0, 0, 180, 0, 0); whl_mesh_transform->setTransform( &wheelpos); whl_mesh_transform->addKid(whl3d); whl_branch->addKid(whl_mesh_transform); } else { whl_branch->addKid(whl3d); } } else { static sgVec2 toffset[4] = { {0.0, 0.5}, {0.5, 0.5}, {0.0, 0.0}, {0.5, 0.0} }; // TORCS's standard generated wheel const int WHL_BRANCH = 16; /* Tread */ { ssgVertexArray *whl_vtx = new ssgVertexArray(2 * WHL_BRANCH); ssgColourArray *whl_clr = new ssgColourArray(2 * WHL_BRANCH); ssgNormalArray *whl_nrm = new ssgNormalArray(1); whl_nrm->add(nrm); clr[3] = 1.0; for (i = 0; i < WHL_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1); vtx[0] = wheelRadius * cos(alpha); vtx[2] = wheelRadius * sin(alpha); vtx[1] = - car->_tireWidth(wheel_index) / 2.0; whl_vtx->add(vtx); vtx[1] = car->_tireWidth(wheel_index) / 2.0; whl_vtx->add(vtx); if (i % 2) { clr[0] = clr[1] = clr[2] = 0.15; } else { clr[0] = clr[1] = clr[2] = 0.0; } whl_clr->add(clr); whl_clr->add(clr); } ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_STRIP, whl_vtx, whl_nrm, NULL, whl_clr); whl->setState(commonState); whl->setCullFace(0); // stripify wheel, should improve performance ssgStripify(whl); whl_branch->addKid(whl); } /* Rim */ switch(wheel_index) { case FRNT_RGT: case REAR_RGT: b_offset = -0.05; break; case FRNT_LFT: case REAR_LFT: b_offset = 0.05; break; } // Make inside rim very dark and take care of normals. float colorfactor[2]; float norm_orig = nrm[1]; if (nrm[1] > 0.0f) { colorfactor[0] = 0.3f; colorfactor[1] = 1.0f; nrm[1] *= -1.0f; } else { colorfactor[0] = 1.0f; colorfactor[1] = 0.3f; } for (k = 0; k < 2; k++) { ssgVertexArray *whl_vtx = new ssgVertexArray(WHL_BRANCH + 1); ssgTexCoordArray *whl_tex = new ssgTexCoordArray(WHL_BRANCH + 1); ssgColourArray *whl_clr = new ssgColourArray(1); ssgNormalArray *whl_nrm = new ssgNormalArray(1); clr[0] = 0.8f*colorfactor[k]; clr[1] = 0.8f*colorfactor[k]; clr[2] = 0.8f*colorfactor[k]; clr[3] = 1.0f; whl_clr->add(clr); whl_nrm->add(nrm); vtx[0] = vtx[2] = 0.0; vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0 - b_offset; whl_vtx->add(vtx); tex[0] = 0.25 + toffset[j][0]; tex[1] = 0.25 + toffset[j][1]; whl_tex->add(tex); vtx[1] = (float)(2 * k - 1) * car->_tireWidth(wheel_index) / 2.0; for (i = 0; i < WHL_BRANCH; i++) { alpha = (float)i * 2.0 * M_PI / (float)(WHL_BRANCH - 1); vtx[0] = wheelRadius * cos(alpha); vtx[2] = wheelRadius * sin(alpha); whl_vtx->add(vtx); tex[0] = 0.25 + 0.25 * cos(alpha) + toffset[j][0]; tex[1] = 0.25 + 0.25 * sin(alpha) + toffset[j][1]; whl_tex->add(tex); } ssgVtxTable *whl = new ssgVtxTable(GL_TRIANGLE_FAN, whl_vtx, whl_nrm, whl_tex, whl_clr); whl->setState(grCarInfo[grCarIndex].wheelTexture); whl->setCullFace(0); // stripify rim, should improve performance ssgStripify(whl); whl_branch->addKid(whl); // Swap normal for "inside" rim face. nrm[1] *= -1.0; } nrm[1] = norm_orig; } whselector->addKid(whl_branch); } return wheel; }
void grInitCar(tCarElt *car) { const int BUFSIZE=4096; char buf[BUFSIZE]; int index; int selIndex; ssgEntity *carEntity; ssgSelector *LODSel; ssgTransform *wheel[4]; int nranges; int i, j; void *handle; const char *param; int lg; const int PATHSIZE=256; char path[PATHSIZE]; myLoaderOptions options; sgVec3 lightPos; int lightNum; const char *lightType; int lightTypeNum; if (!CarsAnchorTmp) { CarsAnchorTmp = new ssgBranch(); } grInitBoardCar(car); TRACE_GL("loadcar: start"); ssgSetCurrentOptions ( &options ) ; grCarIndex = index = car->index; /* current car's index */ handle = car->_carHandle; /* Load visual attributes */ car->_exhaustNb = GfParmGetEltNb(handle, SECT_EXHAUST); car->_exhaustNb = MIN(car->_exhaustNb, 2); car->_exhaustPower = GfParmGetNum(handle, SECT_EXHAUST, PRM_POWER, NULL, 1.0); for (i = 0; i < car->_exhaustNb; i++) { snprintf(path, PATHSIZE, "%s/%d", SECT_EXHAUST, i + 1); car->_exhaustPos[i].x = GfParmGetNum(handle, path, PRM_XPOS, NULL, -car->_dimension_x / 2.0); car->_exhaustPos[i].y = -GfParmGetNum(handle, path, PRM_YPOS, NULL, car->_dimension_y / 2.0); car->_exhaustPos[i].z = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0.1); } snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, SECT_LIGHT); lightNum = GfParmGetEltNb(handle, path); for (i = 0; i < lightNum; i++) { snprintf(path, PATHSIZE, "%s/%s/%d", SECT_GROBJECTS, SECT_LIGHT, i + 1); lightPos[0] = GfParmGetNum(handle, path, PRM_XPOS, NULL, 0); lightPos[1] = GfParmGetNum(handle, path, PRM_YPOS, NULL, 0); lightPos[2] = GfParmGetNum(handle, path, PRM_ZPOS, NULL, 0); lightType = GfParmGetStr(handle, path, PRM_TYPE, ""); lightTypeNum = LIGHT_NO_TYPE; if (!strcmp(lightType, VAL_LIGHT_HEAD1)) { lightTypeNum = LIGHT_TYPE_FRONT; } else if (!strcmp(lightType, VAL_LIGHT_HEAD2)) { lightTypeNum = LIGHT_TYPE_FRONT2; } else if (!strcmp(lightType, VAL_LIGHT_BRAKE)) { lightTypeNum = LIGHT_TYPE_BRAKE; } else if (!strcmp(lightType, VAL_LIGHT_BRAKE2)) { lightTypeNum = LIGHT_TYPE_BRAKE2; } else if (!strcmp(lightType, VAL_LIGHT_REAR)) { lightTypeNum = LIGHT_TYPE_REAR; } grAddCarlight(car, lightTypeNum, lightPos, GfParmGetNum(handle, path, PRM_SIZE, NULL, 0.2)); } grLinkCarlights(car); GfOut("[gr] Init(%d) car %s for driver %s index %d\n", index, car->_carName, car->_modName, car->_driverIndex); grFilePath = (char*)malloc(BUFSIZE); lg = 0; lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d/%s;", car->_modName, car->_driverIndex, car->_carName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%d;", car->_modName, car->_driverIndex); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s/%s;", car->_modName, car->_carName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "drivers/%s;", car->_modName); lg += snprintf(grFilePath + lg, BUFSIZE - lg, "cars/%s", car->_carName); param = GfParmGetStr(handle, SECT_GROBJECTS, PRM_WHEEL_TEXTURE, ""); if (strlen(param) != 0) { grGammaValue = 1.8; grMipMap = 0; grCarInfo[index].wheelTexture = grSsgLoadTexState(param); } grCarInfo[index].envSelector = (ssgStateSelector*)grEnvSelector->clone(); grCarInfo[index].envSelector->ref(); /* the base transformation of the car (rotation + translation) */ grCarInfo[index].carTransform = new ssgTransform; DBG_SET_NAME(grCarInfo[index].carTransform, car->_modName, index, -1); /* Level of details */ grCarInfo[index].LODSelector = LODSel = new ssgSelector; grCarInfo[index].carTransform->addKid(LODSel); snprintf(path, PATHSIZE, "%s/%s", SECT_GROBJECTS, LST_RANGES); nranges = GfParmGetEltNb(handle, path) + 1; if (nranges < 2) { GfOut("Error not enough levels of detail\n"); FREEZ(grFilePath); return; } /* First LOD */ ssgBranch *carBody = new ssgBranch; DBG_SET_NAME(carBody, "LOD", index, 0); LODSel->addKid(carBody); /* The car's model is under cars/<model> */ snprintf(buf, BUFSIZE, "cars/%s", car->_carName); ssgModelPath(buf); snprintf(buf, BUFSIZE, "drivers/%s/%d;drivers/%s;cars/%s", car->_modName, car->_driverIndex, car->_modName, car->_carName); ssgTexturePath(buf); grTexturePath = strdup(buf); /* loading raw car level 0*/ selIndex = 0; /* current selector index */ snprintf(buf, BUFSIZE, "%s.ac", car->_carName); /* default car name */ snprintf(path, PATHSIZE, "%s/%s/1", SECT_GROBJECTS, LST_RANGES); param = GfParmGetStr(handle, path, PRM_CAR, buf); grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, path, PRM_THRESHOLD, NULL, 0.0); /*carEntity = ssgLoad(param);*/ carEntity = grssgCarLoadAC3D(param, NULL, index); grCarInfo[index].carEntity = carEntity; /* Set a selector on the driver */ char* stmp = strdup("DRIVER"); ssgBranch *b = (ssgBranch *)carEntity->getByName(stmp); free(stmp); grCarInfo[index].driverSelector = new ssgSelector; if (b) { ssgBranch *bp = b->getParent(0); bp->addKid(grCarInfo[index].driverSelector); grCarInfo[index].driverSelector->addKid(b); bp->removeKid(b); grCarInfo[index].driverSelector->select(1); grCarInfo[index].driverSelectorinsg = true; } else { grCarInfo[index].driverSelectorinsg = false; } DBG_SET_NAME(carEntity, "Body", index, -1); carBody->addKid(carEntity); /* add wheels */ for (i = 0; i < 4; i++){ wheel[i] = initWheel(car, i); carBody->addKid(wheel[i]); } grCarInfo[index].LODSelectMask[0] = 1 << selIndex; /* car mask */ selIndex++; grCarInfo[index].sx=carTrackRatioX; grCarInfo[index].sy=carTrackRatioY; /* Other LODs */ for (i = 2; i < nranges; i++) { carBody = new ssgBranch; snprintf(buf, BUFSIZE, "%s/%s/%d", SECT_GROBJECTS, LST_RANGES, i); param = GfParmGetStr(handle, buf, PRM_CAR, ""); grCarInfo[index].LODThreshold[selIndex] = GfParmGetNum(handle, buf, PRM_THRESHOLD, NULL, 0.0); /* carEntity = ssgLoad(param); */ carEntity = grssgCarLoadAC3D(param, NULL, index);; DBG_SET_NAME(carEntity, "LOD", index, i-1); carBody->addKid(carEntity); if (!strcmp(GfParmGetStr(handle, buf, PRM_WHEELSON, "no"), "yes")) { /* add wheels */ for (j = 0; j < 4; j++){ carBody->addKid(wheel[j]); } } LODSel->addKid(carBody); grCarInfo[index].LODSelectMask[i-1] = 1 << selIndex; /* car mask */ selIndex++; } /* default range selection */ LODSel->select(grCarInfo[index].LODSelectMask[0]); CarsAnchor->addKid(grCarInfo[index].carTransform); //grCarInfo[index].carTransform->print(stdout, "-", 1); FREEZ(grTexturePath); FREEZ(grFilePath); TRACE_GL("loadcar: end"); }
/** \brief The constructor. * * Loads an airplane model from an xml description. The 3D model * will be added to the specified scenegraph. * * \param xml XML model description file * \param graph Pointer to the scenegraph which shall render the model */ CRRCAirplaneLaRCSimSSG::CRRCAirplaneLaRCSimSSG(SimpleXMLTransfer* xml, ssgBranch *graph) : CRRCAirplaneLaRCSim(xml), initial_trans(NULL), model_trans(NULL), model(NULL), shadow(NULL), shadow_trans(NULL) { printf("CRRCAirplaneLaRCSimSSG(xml, branch)\n"); std::string s; s = XMLModelFile::getGraphics(xml)->getString("model"); // plib automatically loads the texture file, but it does not know which directory to use. { // where is the object file? std::string of = FileSysTools::getDataPath("objects/" + s); // compile and set relative texture path std::string tp = of.substr(0, of.length()-s.length()-1-7) + "textures"; ssgTexturePath(tp.c_str()); // load model model = ssgLoad(of.c_str()); } if (model != NULL) { // Offset of center of gravity CRRCMath::Vector3 pCG; pCG = CRRCMath::Vector3(0, 0, 0); if (xml->indexOfChild("CG") >= 0) { SimpleXMLTransfer* i; i = xml->getChild("CG"); pCG.r[0] = i->attributeAsDouble("x", 0); pCG.r[1] = i->attributeAsDouble("y", 0); pCG.r[2] = i->attributeAsDouble("z", 0); if (i->attributeAsInt("units") == 1) pCG *= M_TO_FT; } // transform model from SSG coordinates to CRRCsim coordinates initial_trans = new ssgTransform(); model_trans = new ssgTransform(); graph->addKid(model_trans); model_trans->addKid(initial_trans); initial_trans->addKid(model); sgMat4 it = { {1.0, 0.0, 0.0, 0}, {0.0, 0.0, -1.0, 0}, {0.0, 1.0, 0.0, 0}, {pCG.r[1], pCG.r[2], -pCG.r[0], 1.0} }; initial_trans->setTransform(it); // add a simple shadow shadow = (ssgEntity*)initial_trans->clone(SSG_CLONE_RECURSIVE | SSG_CLONE_GEOMETRY | SSG_CLONE_STATE); makeShadow(shadow); shadow_trans = new ssgTransform(); graph->addKid(shadow_trans); shadow_trans->addKid(shadow); // add animations ("real" model only, without shadow) initAnimations(xml, model, &Global::inputs, animations); } else { std::string msg = "Unable to open airplane model file \""; msg += s; msg += "\"\nspecified in \""; msg += xml->getSourceDescr(); msg += "\""; throw std::runtime_error(msg); } }
ModelBasedScenery::ModelBasedScenery(SimpleXMLTransfer *xml, int sky_variant) : Scenery(xml, sky_variant), location(Scenery::MODEL_BASED) { ssgEntity *model = NULL; SimpleXMLTransfer *scene = xml->getChild("scene", true); getHeight_mode = scene->attributeAsInt("getHeight_mode", DEFAULT_HEIGHT_MODE); //std::cout << "----getHeight_mode : " << getHeight_mode <<std::endl; SceneGraph = new ssgRoot(); // Create an "invisible" state. This state actually makes a node // visible in a predefined way. This is used to visualize invisible // objects (e.g. collision boxes). invisible_state = new ssgSimpleState(); invisible_state->disable(GL_COLOR_MATERIAL); invisible_state->disable(GL_TEXTURE_2D); invisible_state->enable(GL_LIGHTING); invisible_state->enable(GL_BLEND); //invisible_state->setShadeModel(GL_SMOOTH); //invisible_state->setShininess(0.0f); invisible_state->setMaterial(GL_EMISSION, 0.0, 0.0, 0.0, 0.0); invisible_state->setMaterial(GL_AMBIENT, 1.0, 0.0, 0.0, 0.5); invisible_state->setMaterial(GL_DIFFUSE, 1.0, 0.0, 0.0, 0.5); invisible_state->setMaterial(GL_SPECULAR, 1.0, 0.0, 0.0, 0.5); // transform everything from SSG coordinates to CRRCsim coordinates initial_trans = new ssgTransform(); SceneGraph->addKid(initial_trans); //10.76 sgMat4 it = { {1, 0.0, 0.0, 0}, {0.0, 0.0, -1, 0}, {0.0, 1, 0.0, 0}, {0.0, 0.0, 0.0, 1.0} }; initial_trans->setTransform(it); // find all "objects" defined in the file int num_children = scene->getChildCount(); for (int cur_child = 0; cur_child < num_children; cur_child++) { SimpleXMLTransfer *kid = scene->getChildAt(cur_child); // only use "object" tags if (kid->getName() == "object") { std::string filename = kid->attribute("filename", "not_specified"); bool is_terrain = (kid->attributeAsInt("terrain", 1) != 0); bool is_visible = (kid->attributeAsInt("visible", 1) != 0); // PLIB automatically loads the texture file, // but it does not know which directory to use. // Where is the object file? std::string of = FileSysTools::getDataPath("objects/" + filename, TRUE); // compile and set relative texture path std::string tp = of.substr(0, of.length()-filename.length()-1-7) + "textures"; ssgTexturePath(tp.c_str()); // load model std::cout << "Loading 3D object \"" << of.c_str() << "\""; if (is_terrain) { std::cout << " (part of terrain)"; } if (!is_visible) { std::cout << " (invisible)"; } std::cout << std::endl; model = ssgLoad(of.c_str()); if (model != NULL) { if (!is_visible) { setToInvisibleState(model); } // The model may contain internal node attributes (e.g. for // integrated collision boxes). Parse these attributes now. evaluateNodeAttributes(model); // now parse the instances and place the model in the SceneGraph for (int cur_instance = 0; cur_instance < kid->getChildCount(); cur_instance++) { SimpleXMLTransfer *instance = kid->getChildAt(cur_instance); if (instance->getName() == "instance") { sgCoord coord; // try north/east/height first, then fallback to x/y/z try { coord.xyz[SG_X] = instance->attributeAsDouble("east"); } catch (XMLException &e) { coord.xyz[SG_X] = instance->attributeAsDouble("y", 0.0); } try { coord.xyz[SG_Y] = instance->attributeAsDouble("north"); } catch (XMLException &e) { coord.xyz[SG_Y] = instance->attributeAsDouble("x", 0.0); } try { coord.xyz[SG_Z] = instance->attributeAsDouble("height"); } catch (XMLException &e) { coord.xyz[SG_Z] = instance->attributeAsDouble("z", 0.0); } coord.hpr[0] = 180 - instance->attributeAsDouble("h", 0.0); coord.hpr[1] = -instance->attributeAsDouble("p", 0.0); coord.hpr[2] = -instance->attributeAsDouble("r", 0.0); std::cout << std::setprecision(1); std::cout << " Placing instance at " << coord.xyz[SG_X] << ";" << coord.xyz[SG_Y] << ";" << coord.xyz[SG_Z]; std::cout << ", orientation " << (180-coord.hpr[0]) << ";" << -coord.hpr[1] << ";" << -coord.hpr[2] << std::endl; std::cout << std::setprecision(6); ssgTransform *trans = new ssgTransform(); trans->setTransform(&coord); // In PLIB::SSG, intersection testing is done by a tree-walking // function. This can be influenced by the tree traversal mask // bits. The HOT and LOS flags are cleared for objects that are // not part of the terrain, so that the height-of-terrain and // line-of-sight algorithms ignore this branch of the tree. if (!is_terrain) { trans->clrTraversalMaskBits(SSGTRAV_HOT | SSGTRAV_LOS); } // Objects are made invisible by clearing the CULL traversal flag. // This means that ssgCullAndDraw will ignore this branch. if (!is_visible) { trans->clrTraversalMaskBits(SSGTRAV_CULL); } initial_trans->addKid(trans); trans->addKid(model); } } } } } // create actual terrain height model if (getHeight_mode == 1) { heightdata = new HD_TabulatedTerrain(SceneGraph); } else if (getHeight_mode == 2) { heightdata = new HD_TilingTerrain(SceneGraph); } else { heightdata = new HD_SsgLOSTerrain(SceneGraph); } //wind SimpleXMLTransfer *wind = xml->getChild("wind", true); std::string wind_filename = wind->attribute("filename",""); #if WINDDATA3D == 1 wind_data = 0;//default : no wind_data std::string wind_position_unit = wind->attribute("unit",""); try { flDefaultWindDirection = wind->attributeAsInt("direction"); ImposeWindDirection = true; } catch (XMLException) { // if not attribut "direction", normal mode } if (wind_position_unit.compare("m")==0) { wind_position_coef = FT_TO_M; } else { wind_position_coef = 1; } std::cout << "wind file name : " << wind_filename.c_str()<< std::endl; if (wind_filename.length() > 0) { wind_filename = FileSysTools::getDataPath(wind_filename); std::cout << "init wind ---------"; int n = init_wind_data((wind_filename.c_str())); std::cout << n << " points processed" << std::endl; } #else if (wind_filename.length() > 0) { new CGUIMsgBox("Insufficient configuration to read windfields."); } #endif }
int grLoadScene(tTrack *track) { void *hndl = grTrackHandle; char *acname; ssgEntity *desc; char buf[256]; if (maxTextureUnits==0) { InitMultiTex(); } ssgSetCurrentOptions(&options); ssgAddTextureFormat(".png", grLoadPngTexture); grRegisterCustomSGILoader(); grTrack = track; TheScene = new ssgRoot; /* Landscape */ LandAnchor = new ssgBranch; TheScene->addKid(LandAnchor); /* Pit stops walls */ PitsAnchor = new ssgBranch; TheScene->addKid(PitsAnchor); /* Skid Marks */ SkidAnchor = new ssgBranch; TheScene->addKid(SkidAnchor); /* Car shadows */ ShadowAnchor = new ssgBranch; TheScene->addKid(ShadowAnchor); /* Car lights */ CarlightAnchor = new ssgBranch; TheScene->addKid(CarlightAnchor); /* Cars */ CarsAnchor = new ssgBranch; TheScene->addKid(CarsAnchor); /* Smoke */ SmokeAnchor = new ssgBranch; TheScene->addKid(SmokeAnchor); /* Lens Flares */ SunAnchor = new ssgBranch; TheScene->addKid(SunAnchor); initBackground(); grWrldX = (int)(track->max.x - track->min.x + 1); grWrldY = (int)(track->max.y - track->min.y + 1); grWrldZ = (int)(track->max.z - track->min.z + 1); grWrldMaxSize = (int)(MAX(MAX(grWrldX, grWrldY), grWrldZ)); acname = GfParmGetStr(hndl, TRK_SECT_GRAPH, TRK_ATT_3DDESC, "track.ac"); if (strlen(acname) == 0) { return -1; } sprintf(buf, "tracks/%s/%s;data/textures;data/img;.", grTrack->category, grTrack->internalname); ssgTexturePath(buf); sprintf(buf, "tracks/%s/%s", grTrack->category, grTrack->internalname); ssgModelPath(buf); desc = grssgLoadAC3D(acname, NULL); LandAnchor->addKid(desc); return 0; }