void CIGLoader::load() { for (int i=sizeof(IGFiles)/sizeof(IGFiles[0]);i--;) { try { uint k; CInstanceGroup ig; CIFile inputStream; if (!inputStream.open(IGFiles[i])) { nlinfo("unable to open %s", argv[1]); return -1; } ig.serial(inputStream); CVector gpos = ig.getGlobalPos(); // the origin for the ig for(k = 0; k < ig._InstancesInfos.size(); ++k) { nlinfo("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z); } } catch (std::exception &e) { nlinfo(e.what()); } } }
// *************************************************************************** CInstanceGroup* LoadInstanceGroup (const char* sFilename) { CIFile file; CInstanceGroup *newIG = new CInstanceGroup; if( file.open( sFilename ) ) { try { newIG->serial (file); } catch (const Exception &) { // Cannot save the file delete newIG; return NULL; } } else { delete newIG; return NULL; } return newIG; }
// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- CInstanceGroup* LoadInstanceGroup(const char* sFilename) { CIFile file; CInstanceGroup *newIG = new CInstanceGroup; if( file.open( CPath::lookup( string(sFilename) ) ) ) { try { // Serial the skeleton newIG->serial (file); // All is good } catch (const Exception &) { // Cannot save the file delete newIG; return NULL; } } return newIG; }
// --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void LoadSceneScript (const char *ScriptName, CScene* pScene, vector<SDispCS> &DispCS, CVector &CameraStart, vector<CInstanceGroup*> &vIGs) { char nameIG[256]; float posx, posy, posz; float roti, rotj, rotk; FILE *f = fopen (CPath::lookup(ScriptName).c_str(),"rb"); fseek (f, 0, SEEK_END); uint file_size = ftell (f); fseek (f, 0, SEEK_SET); char *file_buf = (char*)malloc(file_size+1); if (fread (file_buf, 1, file_size, f) != file_size) nlwarning("Can't read %d elements", file_size); file_buf[file_size] = 0; ++file_size; fclose (f); char *buf_ptr = file_buf; sint nLastNbPlus = 0; vector<CInstanceGroup*> pile; pile.clear (); pile.push_back (pScene->getGlobalInstanceGroup()); pile.push_back (pScene->getGlobalInstanceGroup()); do { char Line[256], *line_ptr; sint nNbPlus = 0; line_ptr = &Line[0]; buf_ptr = readLine (line_ptr, buf_ptr); while ((*line_ptr == '\t') || (*line_ptr == ' ') || (*line_ptr == '+')) { if (*line_ptr == '+') ++nNbPlus; ++line_ptr; } if (strlen (line_ptr) == 0) continue; if (*line_ptr == '/') continue; posx = posy = posz = roti = rotj = rotk = 0.0f; sscanf (line_ptr, "%s %f %f %f %f %f %f", nameIG, &posx, &posy, &posz, &roti, &rotj, &rotk); if (stricmp (nameIG, "CAMERA_START") == 0) { CameraStart = CVector(posx, posy, posz); } else { if (nLastNbPlus >= nNbPlus) for (int i = 0; i < ((nLastNbPlus-nNbPlus)+1); ++i) pile.pop_back(); nLastNbPlus = nNbPlus; CInstanceGroup *father = pile.back(); CInstanceGroup *ITemp = LoadInstanceGroup (nameIG); if (ITemp != NULL) { SDispCS dcsTemp; dcsTemp.Name = ""; for (sint32 i = 0; i < (1+nNbPlus); ++i) dcsTemp.Name += " "; dcsTemp.Name += nameIG; dcsTemp.pIG = ITemp; DispCS.push_back (dcsTemp); ITemp->createRoot (*pScene); ITemp->setPos (CVector(posx, posy, posz)); ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::I, roti)); ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::J, rotj)); ITemp->setRotQuat (ITemp->getRotQuat() * CQuat(CVector::K, rotk)); ITemp->setClusterSystemForInstances (father); ITemp->addToScene (*pScene); vIGs.push_back (ITemp); } pile.push_back (ITemp); } } //while (strlen(buf_ptr) > 0); while (buf_ptr < (file_buf+file_size-1)); free (file_buf); }
int main(int argc, char **argv) { if (argc != 2) { printf("usage : %s file.ig\n", argv[0]); return -1; } try { uint k; CInstanceGroup ig; CIFile inputStream; if (!inputStream.open(string(argv[1]))) { printf("unable to open %s\n", argv[1]); return -1; } ig.serial(inputStream); printf("Origine\n"); printf("---------\n"); CVector gpos = ig.getGlobalPos(); printf("global pos : x = %.1f, y = %.1f, z =%.1f\n", gpos.x, gpos.y, gpos.z); printf("Instances\n"); printf("---------\n"); for(k = 0; k < ig._InstancesInfos.size(); ++k) { printf("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f\n", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z); } printf("\n"); printf("Lights\n"); printf("---------\n"); for(k = 0; k < ig.getNumPointLights(); ++k) { const CPointLightNamed &pl = ig.getPointLightNamed(k); printf("light group = %d, anim = \"%s\" x = %.1f, y = %.1f, z = %.1f\n", pl.LightGroup, pl.AnimatedLight.c_str(), pl.getPosition().x + gpos.x, pl.getPosition().y + gpos.y, pl.getPosition().z + gpos.z); } printf("---------\n"); printf("Realtime sun contribution = %s\n", ig.getRealTimeSunContribution() ? "on" : "off"); printf("---------\n"); // IGSurfaceLight info. const CIGSurfaceLight::TRetrieverGridMap &rgm= ig.getIGSurfaceLight().getRetrieverGridMap(); printf("IGSurfaceLighting: CellSize: %f. NumGridRetriever: %u\n", ig.getIGSurfaceLight().getCellSize(), (uint)rgm.size() ); uint rgmInst= 0; uint totalCells= 0; CIGSurfaceLight::TRetrieverGridMap::const_iterator it= rgm.begin(); for(;it!=rgm.end();it++) { for(uint i=0;i<it->second.Grids.size();i++) { printf("grid(%d, %d): %dx%d\n", rgmInst, i, it->second.Grids[i].Width, it->second.Grids[i].Height ); totalCells+= it->second.Grids[i].Cells.size(); } rgmInst++; } printf("TotalCells: %d\n", totalCells); } catch (const std::exception &e) { printf("%s\n", e.what()); } }
//======================================================================================= // ryzom specific build bbox of a village in a zone static void computeBBoxFromVillage(const NLGEORGES::UFormElm *villageItem, const std::string &continentName, uint villageIndex, TShapeMap &shapeMap, CLightingBBox &result ) { result = CLightingBBox(); const NLGEORGES::UFormElm *igNamesItem; if (! (villageItem->getNodeByName (&igNamesItem, "IgList") && igNamesItem) ) { nlwarning("No list of IGs was found in the continent form %s, village #%d", continentName.c_str(), villageIndex); return; } // Get number of village uint numIgs; nlverify (igNamesItem->getArraySize (numIgs)); const NLGEORGES::UFormElm *currIg; for(uint l = 0; l < numIgs; ++l) { if (!(igNamesItem->getArrayNode (&currIg, l) && currIg)) { nlwarning("Couldn't get ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex); continue; } const NLGEORGES::UFormElm *igNameItem; currIg->getNodeByName (&igNameItem, "IgName"); std::string igName; if (!igNameItem->getValue (igName)) { nlwarning("Couldn't get ig name of ig #%d in the continent form %s, in village #%d", l, continentName.c_str(), villageIndex); continue; } if (igName.empty()) { nlwarning("Ig name of ig #%d in the continent form %s, in village #%d is an empty string", l, continentName.c_str(), villageIndex); continue; } igName = CFile::getFilenameWithoutExtension(igName) + ".ig"; string nameLookup = CPath::lookup (igName, false, true); if (!nameLookup.empty()) { CIFile inputFile; // Try to open the file if (inputFile.open (nameLookup)) { CInstanceGroup group; try { CLightingBBox currBBox; group.serial (inputFile); computeIGBBox(group, currBBox, shapeMap); result.makeUnion(currBBox); } catch(NLMISC::Exception &) { nlwarning ("Error while loading instance group %s\n", igName.c_str()); continue; } inputFile.close(); } else { // Error nlwarning ("Can't open instance group %s\n", igName.c_str()); } } } }
int main(int argc, char **argv) { // Filter addSearchPath NLMISC::createDebug(); InfoLog->addNegativeFilter("adding the path"); createDebug(); try { // Init init(); uint i, j, k; for (i=0; i<IGs.size(); ++i) { // load ig associated to the zone string igName = IGs[i]+".ig"; CIFile igStream(CPath::lookup(igName)); CInstanceGroup ig; igStream.serial(ig); CAABBox igBBox; bool boxSet = false; nlinfo("Generating BBOX for %s", igName.c_str()); // search in group for water instance for (j=0; j<ig._InstancesInfos.size(); ++j) { /* Ben: c'est degueulasse, mais c'est les coders a la 3D, y savent pas coder Hld: ouai, mais ca marche pas ton truc, alors p'tet qu'on sait pas coder mais toi non plus :p Special Dedicace to SupaGreg! string shapeName = ig._InstancesInfos[j].Name+".shape"; */ string shapeName = ig._InstancesInfos[j].Name; if (CFile::getExtension (shapeName) == "") shapeName += ".shape"; if (NonWaterShapes.find(shapeName) != NonWaterShapes.end()) continue; string shapeNameLookup = CPath::lookup (shapeName, false, false); if (!shapeNameLookup.empty()) { CIFile f; if (f.open (shapeNameLookup)) { CShapeStream shape; shape.serial(f); CWaterShape *wshape = dynamic_cast<CWaterShape *>(shape.getShapePointer()); if (wshape == NULL) { NonWaterShapes.insert(shapeName); continue; } CMatrix matrix; ig.getInstanceMatrix(j, matrix); CPolygon wpoly; wshape->getShapeInWorldSpace(wpoly); for (k=0; k<wpoly.Vertices.size(); ++k) { if (boxSet) { igBBox.extend(matrix * wpoly.Vertices[k]); } else { igBBox.setCenter(matrix * wpoly.Vertices[k]); boxSet = true; } } } else { nlwarning ("Can't load shape %s", shapeNameLookup.c_str()); } } else { NonWaterShapes.insert(shapeName); } } if (boxSet) { Boxes.push_back(CIGBox(igName, igBBox)); nlinfo("Bbox: (%.1f,%.1f)-(%.1f,%.1f)", igBBox.getMin().x, igBBox.getMin().y, igBBox.getMax().x, igBBox.getMax().y); } } COFile output(Output); output.serialCont(Boxes); } catch (Exception &e) { fprintf (stderr,"main trapped an exception: '%s'\n", e.what ()); } #ifndef NL_DEBUG catch (...) { fprintf(stderr,"main trapped an unknown exception\n"); } #endif // NL_DEBUG return 0; }
// *************************************************************************** void CIgLighterLib::lightIg(CInstanceLighter &instanceLighter, const CInstanceGroup &igIn, CInstanceGroup &igOut, CInstanceLighter::CLightDesc &lightDesc, CSurfaceLightingInfo &slInfo, const char *igName) { sint i; // Setup. //======= // Init instanceLighter.init(); // For interiors ig, disable Sun contrib according to ig. lightDesc.DisableSunContribution= !igIn.getRealTimeSunContribution(); // Copy it to igOut, just to keep same setup data for in and out. igOut.enableRealTimeSunContribution(!lightDesc.DisableSunContribution); // Add obstacles. std::vector<CInstanceLighter::CTriangle> obstacles; // only if Shadowing On. if(lightDesc.Shadow) { // Map of shape to load std::map<string, IShape*> shapeMap; // For all instances of igIn. for(i=0; i<(sint)igIn.getNumInstance();i++) { // progress instanceLighter.progress("Loading Shapes obstacles", float(i)/igIn.getNumInstance()); // Skip it?? IgLighterLib use the DontCastShadowForInterior flag. See doc of this flag if(igIn.getInstance(i).DontCastShadow || igIn.getInstance(i).DontCastShadowForInterior) continue; // Get the instance shape name string name= igIn.getShapeName(i); bool shapeFound= true; // Try to find the shape in the UseShapeMap. std::map<string, IShape*>::const_iterator iteMap= lightDesc.UserShapeMap.find (name); // If not found in userShape map, try to load it from the temp loaded ShapeBank. if( iteMap == lightDesc.UserShapeMap.end() ) { // Add a .shape at the end ? if (name.find('.') == std::string::npos) name += ".shape"; // Lookup the file string nameLookup = CPath::lookup (name, false, false); if (!nameLookup.empty()) name = nameLookup; // Find the shape in the bank iteMap= shapeMap.find (name); if (iteMap==shapeMap.end()) { // Input file CIFile inputFile; if (inputFile.open (name)) { // Load it CShapeStream stream; stream.serial (inputFile); // Get the pointer iteMap=shapeMap.insert (std::map<string, IShape*>::value_type (name, stream.getShapePointer ())).first; } else { // Error nlwarning ("WARNING can't load shape %s\n", name.c_str()); shapeFound= false; } } } if(shapeFound) { CMatrix matInst; matInst.setPos(igIn.getInstancePos(i)); matInst.setRot(igIn.getInstanceRot(i)); matInst.scale(igIn.getInstanceScale(i)); // Add triangles of this shape CInstanceLighter::addTriangles(*iteMap->second, matInst, obstacles, i); } } // Clean Up shapes. //----------- std::map<string, IShape*>::iterator iteMap; iteMap= shapeMap.begin(); while(iteMap!= shapeMap.end()) { // delte shape delete iteMap->second; // delete entry in map shapeMap.erase(iteMap); // next iteMap= shapeMap.begin(); } } // Add pointLights of the IG. for(i=0; i<(sint)igIn.getPointLightList().size();i++) { instanceLighter.addStaticPointLight( igIn.getPointLightList()[i], igName ); } // Setup a CIGSurfaceLightBuild if needed. //======= CIGSurfaceLightBuild *igSurfaceLightBuild= NULL; CGlobalRetriever *globalRetriever= slInfo.GlobalRetriever; CRetrieverBank *retrieverBank= slInfo.RetrieverBank; float cellSurfaceLightSize= slInfo.CellSurfaceLightSize; if(retrieverBank && globalRetriever) { igSurfaceLightBuild= new CIGSurfaceLightBuild; igSurfaceLightBuild->CellSize= cellSurfaceLightSize; // col Identifier. string colIdent= slInfo.ColIdentifierPrefix + slInfo.IgFileName + slInfo.ColIdentifierSuffix; // For any retreiverInstance with this identifier. //---------------- uint numInstances= (uint)globalRetriever->getInstances().size(); for(uint instanceId=0; instanceId<numInstances; instanceId++) { const CRetrieverInstance &instance= globalRetriever->getInstance(instanceId); // If this instance is an interior if ( instance.getType() == CLocalRetriever::Interior ) { uint localRetrieverId= instance.getRetrieverId(); const CLocalRetriever &localRetriever= retrieverBank->getRetriever(localRetrieverId); // get the identifer of this localRetriever string retIdent= localRetriever.getIdentifier(); // Match the ident?? if( retIdent.find(colIdent)!=string::npos ) { // check CRetrieverLightGrid not already present CIGSurfaceLightBuild::ItRetrieverGridMap itRgm; itRgm= igSurfaceLightBuild->RetrieverGridMap.find(localRetrieverId); if( itRgm != igSurfaceLightBuild->RetrieverGridMap.end() ) { nlwarning ("ERROR Found 2 different collision retriever with same identifier: '%s'. The 2nd is discared\n", retIdent.c_str()); } else { // Append CRetrieverLightGrid. itRgm= igSurfaceLightBuild->RetrieverGridMap.insert( make_pair(localRetrieverId, CIGSurfaceLightBuild::CRetrieverLightGrid() ) ).first; CIGSurfaceLightBuild::CRetrieverLightGrid &rlg= itRgm->second; // Resize Grids. uint numSurfaces= (uint)localRetriever.getSurfaces().size(); rlg.Grids.resize( numSurfaces ); // Compute the bbox for all surfaces. (NB: local to the localRetriever). vector<CAABBox> surfaceBBoxes; localRetriever.buildInteriorSurfaceBBoxes(surfaceBBoxes); // For each surface, compute it. for(uint surfaceId=0; surfaceId<numSurfaces; surfaceId++) { // Progress. char stmp[256]; sprintf(stmp, "Sample surfaces of %s", retIdent.c_str()); instanceLighter.progress(stmp, surfaceId / float(numSurfaces)); // Compute surface and size of the grid. CIGSurfaceLightBuild::CSurface &surfDst= rlg.Grids[surfaceId]; // Snap Origin on cellSize surfDst.Origin= surfaceBBoxes[surfaceId].getMin(); surfDst.Origin.x= floorf(surfDst.Origin.x/cellSurfaceLightSize) * cellSurfaceLightSize; surfDst.Origin.y= floorf(surfDst.Origin.y/cellSurfaceLightSize) * cellSurfaceLightSize; // Snap Width / Height on cellSize. float sizex= surfaceBBoxes[surfaceId].getMax().x - surfDst.Origin.x; float sizey= surfaceBBoxes[surfaceId].getMax().y - surfDst.Origin.y; surfDst.Width= (uint)floorf(sizex/cellSurfaceLightSize) + 2; surfDst.Height= (uint)floorf(sizey/cellSurfaceLightSize) + 2; // Get Zcenter. float zCenter= surfaceBBoxes[surfaceId].getCenter().z; // Allocate elements. surfDst.Cells.resize(surfDst.Width * surfDst.Height); // For all elements for(sint yCell=0; yCell<(sint)surfDst.Height; yCell++) { for(sint xCell=0; xCell<(sint)surfDst.Width; xCell++) { // compute pos of the cell. ULocalPosition localPos; localPos.Estimation.x= surfDst.Origin.x + xCell*cellSurfaceLightSize; localPos.Estimation.y= surfDst.Origin.y + yCell*cellSurfaceLightSize; localPos.Estimation.z= zCenter; // snap the pos to the surface. localPos.Surface= surfaceId; bool snapped; localRetriever.snapToInteriorGround(localPos, snapped); // if snapped then this point is IN the surface. CIGSurfaceLightBuild::CCellCorner &cell= surfDst.Cells[yCell * surfDst.Width + xCell]; cell.InSurface= snapped; // If ok, retrieve the global (ie world) position if(snapped) { // build a valid globalPosition. UGlobalPosition globalPos; globalPos.InstanceId= instanceId; globalPos.LocalPosition= localPos; // retrieve from globalRetriever. cell.CenterPos= globalRetriever->getGlobalPosition(globalPos); // Add a delta to simulate entity center cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ; // OverSample if(lightDesc.OverSampling==0) { // No OverSample, just add CenterPos to the samples. cell.NumOverSamples= 1; cell.OverSamples[0]= cell.CenterPos; } else { // OverSample. overSampleCell(cell, lightDesc.OverSampling, localRetriever, *globalRetriever, instanceId, localPos, cellSurfaceLightSize, slInfo.CellRaytraceDeltaZ); // it is possible that no samples lies in surfaces (small surface). // In this case, just copy CenterPos into samples. if(cell.NumOverSamples==0) { cell.NumOverSamples= 1; cell.OverSamples[0]= cell.CenterPos; } } } else { // For debug mesh only, get an approximate pos. cell.CenterPos= localPos.Estimation + instance.getOrigin(); cell.CenterPos.z+= slInfo.CellRaytraceDeltaZ; } // Init cell defaults cell.Dilated= false; cell.SunContribution= 0; } } } } } } } } // Run. //======= instanceLighter.light(igIn, igOut, lightDesc, obstacles, NULL, igSurfaceLightBuild); // Output a debug mesh?? if(igSurfaceLightBuild && slInfo.BuildDebugSurfaceShape && !igSurfaceLightBuild->RetrieverGridMap.empty() ) { // Do it for the sun and point lights. for(uint i=0;i<2;i++) { // compute CMesh::CMeshBuild meshBuild; CMeshBase::CMeshBaseBuild meshBaseBuild; CVector deltaPos= CVector::Null; deltaPos.z= - slInfo.CellRaytraceDeltaZ + 0.1f; // What kind of debug? if( i==0 ) igSurfaceLightBuild->buildSunDebugMesh(meshBuild, meshBaseBuild, deltaPos); else igSurfaceLightBuild->buildPLDebugMesh(meshBuild, meshBaseBuild, deltaPos, igOut); // build CMesh mesh; mesh.build(meshBaseBuild, meshBuild); // Save. CShapeStream shapeStream; shapeStream.setShapePointer(&mesh); COFile file; if( i==0 ) file.open(slInfo.DebugSunName); else file.open(slInfo.DebugPLName); shapeStream.serial(file); } } // Clean. //======= if(igSurfaceLightBuild) delete igSurfaceLightBuild; }
CInstanceGroup* CExportNel::buildInstanceGroup(const vector<INode*>& vectNode, vector<INode*>& resultInstanceNode, TimeValue tvTime) { // Extract from the node the name, the transformations and the parent CInstanceGroup::TInstanceArray aIGArray; uint32 i, nNumIG; uint32 j,k,m; aIGArray.empty (); resultInstanceNode.empty (); aIGArray.resize (vectNode.size()); resultInstanceNode.resize (vectNode.size()); int nNbInstance = 0; for (i = 0; i < vectNode.size(); ++i) { INode *pNode = vectNode[i]; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { ++nNbInstance; } } // Check integrity of the hierarchy and set the parents std::vector<INode*>::const_iterator it = vectNode.begin(); nNumIG = 0; for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone( *pNode, tvTime )) if (CExportNel::isMesh( *pNode, tvTime ) || CExportNel::isDummy(*pNode, tvTime)) { aIGArray[nNumIG].DontAddToScene = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_DONT_ADD_TO_SCENE, 0)?true:false; aIGArray[nNumIG].InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, ""); resultInstanceNode[nNumIG] = pNode; if (aIGArray[nNumIG].InstanceName == "") // no instance name was set, takes the node name instead { aIGArray[nNumIG].InstanceName = pNode->GetName(); } // Visible? always true, but if special flag for camera collision sint appDataCameraCol= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_CAMERA_COLLISION_MESH_GENERATION, 0); aIGArray[nNumIG].Visible= appDataCameraCol!=3; INode *pParent = pNode->GetParentNode(); // Set the DontCastShadow flag. aIGArray[nNumIG].DontCastShadow= pNode->CastShadows()==0; // Set the Special DontCastShadow flag. aIGArray[nNumIG].DontCastShadowForInterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_INTERIOR, BST_UNCHECKED)?true:false; aIGArray[nNumIG].DontCastShadowForExterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_EXTERIOR, BST_UNCHECKED)?true:false; // Is the pNode has the root node for parent ? if( pParent->IsRootNode() == 0 ) { // Look if the parent is in the selection int nNumIG2 = 0; for (j = 0; j < vectNode.size(); ++j) { INode *pNode2 = vectNode[j]; int nAccelType2 = CExportNel::getScriptAppData (pNode2, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType2&3) == 0) // If not an accelerator if (!RPO::isZone( *pNode2, tvTime )) if (CExportNel::isMesh( *pNode2, tvTime )) { if (pNode2 == pParent) break; ++nNumIG2; } } if (nNumIG2 == nNbInstance) { // The parent is not selected ! link to root aIGArray[nNumIG].nParent = -1; } else { aIGArray[nNumIG].nParent = nNumIG2; } } else { aIGArray[nNumIG].nParent = -1; } ++nNumIG; } } aIGArray.resize( nNumIG ); resultInstanceNode.resize( nNumIG ); // Build the array of node vGlobalPos = CVector(0,0,0); nNumIG = 0; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { CVector vScaleTemp; CQuat qRotTemp; CVector vPosTemp; // Get Nel Name for the object. aIGArray[nNumIG].Name= CExportNel::getNelObjectName(*pNode); //Get the local transformation matrix Matrix3 nodeTM = pNode->GetNodeTM(0); INode *pParent = pNode->GetParentNode(); Matrix3 parentTM = pParent->GetNodeTM(0); Matrix3 localTM = nodeTM*Inverse(parentTM); // Extract transformations CExportNel::decompMatrix (vScaleTemp, qRotTemp, vPosTemp, localTM); aIGArray[nNumIG].Rot = qRotTemp; aIGArray[nNumIG].Pos = vPosTemp; aIGArray[nNumIG].Scale = vScaleTemp; vGlobalPos += vPosTemp; ++nNumIG; } } // todo Make this work (precision): /* vGlobalPos = vGlobalPos / nNumIG; for (i = 0; i < nNumIG; ++i) aIGArray[i].Pos -= vGlobalPos; */ vGlobalPos = CVector(0,0,0); // Temporary !!! // Accelerator Portal/Cluster part //================= // Creation of all the clusters vector<CCluster> vClusters; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, NEL3D_APPDATA_ACCEL_DEFAULT); bool bFatherVisible = nAccelType&NEL3D_APPDATA_ACCEL_FATHER_VISIBLE?true:false; bool bVisibleFromFather = nAccelType&NEL3D_APPDATA_ACCEL_VISIBLE_FROM_FATHER?true:false; bool bAudibleLikeVisible = (nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_NOT_LIKE_VISIBLE)?false:true; bool bFatherAudible = bAudibleLikeVisible ? bFatherVisible : nAccelType&NEL3D_APPDATA_ACCEL_FATHER_AUDIBLE?true:false; bool bAudibleFromFather = bAudibleLikeVisible ? bVisibleFromFather : nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_FROM_FATHER?true:false; if ((nAccelType&NEL3D_APPDATA_ACCEL_TYPE) == NEL3D_APPDATA_ACCEL_CLUSTER) // If cluster if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh(*pNode, tvTime)) { CCluster clusterTemp; std::string temp; temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_SOUND_GROUP, "no sound"); clusterTemp.setSoundGroup(temp != "no sound" ? temp : ""); temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_ENV_FX, "no fx"); clusterTemp.setEnvironmentFx(temp != "no fx" ? temp : ""); CMesh::CMeshBuild *pMB; CMeshBase::CMeshBaseBuild *pMBB; pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); for (j = 0; j < pMB->Faces.size(); ++j) { if (!clusterTemp.makeVolume (pMB->Vertices[pMB->Faces[j].Corner[0].Vertex], pMB->Vertices[pMB->Faces[j].Corner[1].Vertex], pMB->Vertices[pMB->Faces[j].Corner[2].Vertex]) ) { // ERROR : The volume is not convex !!! char tam[256]; sprintf(tam,"ERROR: The cluster %s is not convex.",vectNode[i]->GetName()); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } } clusterTemp.FatherVisible = bFatherVisible; clusterTemp.VisibleFromFather = bVisibleFromFather; clusterTemp.FatherAudible = bFatherAudible; clusterTemp.AudibleFromFather = bAudibleFromFather; clusterTemp.Name = pNode->GetName(); vClusters.push_back (clusterTemp); delete pMB; delete pMBB; } } // Creation of all the portals vector<CPortal> vPortals; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 1) // If Portal if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh(*pNode, tvTime)) { CPortal portalTemp; std::string temp; temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OCC_MODEL, "no occlusion"); portalTemp.setOcclusionModel(temp != "no occlusion" ? temp : ""); temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OPEN_OCC_MODEL, "no occlusion"); portalTemp.setOpenOcclusionModel(temp != "no occlusion" ? temp : ""); CMesh::CMeshBuild *pMB; CMeshBase::CMeshBaseBuild *pMBB; pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); vector<sint32> poly; vector<bool> facechecked; facechecked.resize (pMB->Faces.size()); for (j = 0; j < pMB->Faces.size(); ++j) facechecked[j] = false; poly.push_back(pMB->Faces[0].Corner[0].Vertex); poly.push_back(pMB->Faces[0].Corner[1].Vertex); poly.push_back(pMB->Faces[0].Corner[2].Vertex); facechecked[0] = true; for (j = 0; j < pMB->Faces.size(); ++j) if (!facechecked[j]) { bool found = false; for(k = 0; k < 3; ++k) { for(m = 0; m < poly.size(); ++m) { if ((pMB->Faces[j].Corner[k].Vertex == poly[m]) && (pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[(m+1)%poly.size()])) { found = true; break; } if ((pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[m]) && (pMB->Faces[j].Corner[k].Vertex == poly[(m+1)%poly.size()])) { found = true; break; } } if (found) break; } if (found) { // insert an empty space in poly between m and m+1 poly.resize (poly.size()+1); for (uint32 a = poly.size()-2; a > m; --a) poly[a+1] = poly[a]; poly[m+1] = pMB->Faces[j].Corner[(k+2)%3].Vertex; facechecked[j] = true; j = 0; } } vector<CVector> polyv; polyv.resize (poly.size()); for (j = 0; j < poly.size(); ++j) polyv[j] = pMB->Vertices[poly[j]]; if (!portalTemp.setPoly (polyv)) { // ERROR : Poly not convex, or set of vertices not plane char tam[256]; sprintf(tam,"ERROR: The portal %s is not convex.",vectNode[i]->GetName()); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } if (nAccelType&16) // is dynamic portal ? { string InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, ""); if (!InstanceName.empty()) portalTemp.setName (InstanceName); else portalTemp.setName (string(pNode->GetName())); } // Check if portal has 2 cluster int nNbCluster = 0; for (j = 0; j < vClusters.size(); ++j) { bool bPortalInCluster = true; for (k = 0; k < polyv.size(); ++k) if (!vClusters[j].isIn (polyv[k]) ) { bPortalInCluster = false; break; } if (bPortalInCluster) ++nNbCluster; } if (nNbCluster != 2) { // ERROR char tam[256]; sprintf(tam,"ERROR: The portal %s has not 2 clusters but %d",vectNode[i]->GetName(), nNbCluster); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } vPortals.push_back (portalTemp); delete pMB; delete pMBB; } } // Link instance to clusters (an instance has a list of clusters) nNumIG = 0; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { if (nAccelType&32) // Is the flag clusterize set ? { // Test against all clusters // The list of vertices used to test against cluster std::vector<NLMISC::CVector> *testVertices; std::vector<NLMISC::CVector> FXVertices; // Used only if the obj is a fx. It contains the corners of the bbox. bool buildMeshBBox = true; /** If it is a mesh, we build its bbox and transform in world * If it is a FX, we read its bbox from its shape * If we can't read it, we use the bbox of the fx helper in max */ Object *obj = pNode->EvalWorldState(tvTime).obj; // Check if there is an object if (obj) { Class_ID clid = obj->ClassID(); // is the object a particle system ? if (clid.PartA() == NEL_PARTICLE_SYSTEM_CLASS_ID) { // build the shape from the file name std::string objName = CExportNel::getNelObjectName(*pNode); if (!objName.empty()) { NL3D::CShapeStream ss; NLMISC::CIFile iF; if (iF.open(objName.c_str())) { try { iF.serial(ss); NL3D::CParticleSystemShape *pss = dynamic_cast<NL3D::CParticleSystemShape *>(ss.getShapePointer()); if (!pss) { nlwarning("ERROR: Node %s shape is not a FX", CExportNel::getName(*pNode).c_str()); } else { NLMISC::CAABBox bbox; pss->getAABBox(bbox); // transform in world Matrix3 xForm = pNode->GetNodeTM(tvTime); NLMISC::CMatrix nelXForm; CExportNel::convertMatrix(nelXForm, xForm); bbox = NLMISC::CAABBox::transformAABBox(nelXForm, bbox); // store vertices of the bbox in the list FXVertices.reserve(8); for(uint k = 0; k < 8; ++k) { FXVertices.push_back(CVector(((k & 1) ? 1 : -1) * bbox.getHalfSize().x + bbox.getCenter().x, ((k & 2) ? 1 : -1) * bbox.getHalfSize().y + bbox.getCenter().y, ((k & 4) ? 1 : -1) * bbox.getHalfSize().z + bbox.getCenter().z)); } // testVertices = &FXVertices; buildMeshBBox = false; } delete ss.getShapePointer(); } catch (NLMISC::Exception &e) { nlwarning(e.what()); } } if (buildMeshBBox) { nlwarning("ERROR: Can't get bbox of a particle system from its shape, using helper bbox instead"); } } } } CMesh::CMeshBuild *pMB = NULL; CMeshBase::CMeshBaseBuild *pMBB = NULL; if (buildMeshBBox) { pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); testVertices = &pMB->Vertices; } for(k = 0; k < vClusters.size(); ++k) { bool bMeshInCluster = false; for(j = 0; j < testVertices->size(); ++j) { if (vClusters[k].isIn ((*testVertices)[j])) { bMeshInCluster = true; break; } } if (bMeshInCluster) { aIGArray[nNumIG].Clusters.push_back (k); } } // debug purpose : to remove if (vClusters.size() > 0) if (aIGArray[nNumIG].Clusters.size() == 0) { char tam[256]; sprintf(tam,"ERROR: Object %s is not attached to any cluster\nbut his flag clusterize is set", pNode->GetName()); //MessageBox(NULL, tam, "Warning", MB_OK); nlwarning(tam); } // debug purpose : to remove delete pMB; delete pMBB; } ++nNumIG; } // debug purpose : to remove /* if ((nAccelType&3) == 0) // If not an accelerator if (!(nAccelType&32)) { char tam[256]; sprintf(tam,"Object %s is not clusterized", pNode->GetName()); MessageBox(NULL, tam, "Info", MB_OK); } */ // debug purpose : to remove } // PointLight part //================= bool sunLightEnabled= false; sint nNumPointLight = 0; vector<CPointLightNamed> pointLights; pointLights.resize(vectNode.size()); // For all nodes for (i = 0; i < (sint)vectNode.size(); ++i) { INode *pNode = vectNode[i]; SLightBuild sLightBuild; // If it is a Max Light. if ( sLightBuild.canConvertFromMaxLight(pNode, tvTime) ) { // And if this light is checked to realtime export int nRTExport= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_REALTIME_LIGHT, BST_CHECKED); if(nRTExport == BST_CHECKED) { // get Max Light info. sLightBuild.convertFromMaxLight(pNode, tvTime); // Skip if LightDir if(sLightBuild.Type != SLightBuild::LightDir) { // Fill PointLight Info. NL3D::CPointLightNamed &plNamed= pointLights[nNumPointLight]; // Position plNamed.setPosition(sLightBuild.Position); // Attenuation plNamed.setupAttenuation(sLightBuild.rRadiusMin, sLightBuild.rRadiusMax); // Colors // Ensure A=255 for localAmbient to work. NLMISC::CRGBA ambient= sLightBuild.Ambient; ambient.A= 255; plNamed.setDefaultAmbient(ambient); plNamed.setAmbient(ambient); plNamed.setDefaultDiffuse(sLightBuild.Diffuse); plNamed.setDiffuse(sLightBuild.Diffuse); plNamed.setDefaultSpecular(sLightBuild.Specular); plNamed.setSpecular(sLightBuild.Specular); // GroupName. plNamed.AnimatedLight = sLightBuild.AnimatedLight; plNamed.LightGroup = sLightBuild.LightGroup; // Which light type?? if(sLightBuild.bAmbientOnly || sLightBuild.Type== SLightBuild::LightAmbient) { plNamed.setType(CPointLight::AmbientLight); // Special ambient info int nRTAmbAdd= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_REALTIME_AMBIENT_ADD_SUN, BST_UNCHECKED); plNamed.setAddAmbientWithSun(nRTAmbAdd==BST_CHECKED); } else if(sLightBuild.Type== SLightBuild::LightPoint) { plNamed.setType(CPointLight::PointLight); } else if(sLightBuild.Type== SLightBuild::LightSpot) { plNamed.setType(CPointLight::SpotLight); // Export Spot infos. plNamed.setupSpotDirection(sLightBuild.Direction); plNamed.setupSpotAngle(sLightBuild.rHotspot, sLightBuild.rFallof); } else { // What??? nlstop; } // inc Size ++nNumPointLight; } } // if this light is a directionnal and checked to export as Sun Light int nExportSun= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_AS_SUN_LIGHT, BST_UNCHECKED); if(nExportSun== BST_CHECKED) { // get Max Light info. sLightBuild.convertFromMaxLight(pNode, tvTime); // Skip if not dirLight. if(sLightBuild.Type == SLightBuild::LightDir) sunLightEnabled= true; } } } // Good size pointLights.resize(nNumPointLight); // Build the ig //================= CInstanceGroup* pIG = new CInstanceGroup; // Link portals and clusters and create meta cluster if one pIG->build (vGlobalPos, aIGArray, vClusters, vPortals, pointLights); // IG touched by sun ?? pIG->enableRealTimeSunContribution(sunLightEnabled); return pIG; }
// --------------------------------------------------------------------------- int main(int nNbArg, char**ppArgs) { if (!NLMISC::INelContext::isContextInitialised()) new CApplicationContext(); NL3D_BlockMemoryAssertOnPurge = false; char sCurDir[MAX_PATH]; getcwd (sCurDir, MAX_PATH); if (nNbArg != 2) { printf ("Use : ig_elevation configfile.cfg\n"); printf ("\nExample of config.cfg\n\n"); printf ("InputIGDir = \"ig_land_max\";\n"); printf ("OutputIGDir = \"ig_land_max_elev\";\n"); printf ("CellSize = 160.0;\n"); printf ("HeightMapFile1 = \"w:/database/landscape/ligo/jungle/big.tga\";\n"); printf ("ZFactor1 = 1.0;\n"); printf ("HeightMapFile2 = \"w:/database/landscape/ligo/jungle/noise.tga\";\n"); printf ("ZFactor2 = 0.5;\n"); printf ("LandFile = \"w:/matis.land\";\n"); return -1; } SExportOptions options; if (!options.load(ppArgs[1])) { return -1; } // Get all ig files in the input directory and elevate to the z of the double heightmap // Load the land CZoneRegion *ZoneRegion = loadLand(options.LandFile); CZoneLimits zl; if (ZoneRegion) { zl._ZoneMinX = ZoneRegion->getMinX() < 0 ? 0 : ZoneRegion->getMinX(); zl._ZoneMaxX = ZoneRegion->getMaxX() > 255 ? 255 : ZoneRegion->getMaxX(); zl._ZoneMinY = ZoneRegion->getMinY() > 0 ? 0 : ZoneRegion->getMinY(); zl._ZoneMaxY = ZoneRegion->getMaxY() < -255 ? -255 : ZoneRegion->getMaxY(); } else { nlwarning("A ligo .land file cannot be found"); zl._ZoneMinX = 0; zl._ZoneMaxX = 255; zl._ZoneMinY = 0; zl._ZoneMaxY = 255; } // Load the 2 height maps CBitmap *HeightMap1 = NULL; if (!options.HeightMapFile1.empty()) { HeightMap1 = new CBitmap; try { CIFile inFile; if (inFile.open(options.HeightMapFile1)) { HeightMap1->load (inFile); } else { string sTmp = string("Couldn't not open ")+string(options.HeightMapFile1) +string(" : heightmap 1 map ignored"); outString(sTmp); delete HeightMap1; HeightMap1 = NULL; } } catch (const Exception &e) { string sTmp = string("Cant load height map : ") + options.HeightMapFile1 + " : " + e.what(); outString (sTmp); delete HeightMap1; HeightMap1 = NULL; } } CBitmap *HeightMap2 = NULL; if (!options.HeightMapFile2.empty()) { HeightMap2 = new CBitmap; try { CIFile inFile; if (inFile.open(options.HeightMapFile2)) { HeightMap2->load (inFile); } else { string sTmp = string("Couldn't not open ")+string(options.HeightMapFile2) +string(" : heightmap 2 map ignored\n"); outString(sTmp); delete HeightMap2; HeightMap2 = NULL; } } catch (const Exception &e) { string sTmp = string("Cant load height map : ") + options.HeightMapFile2 + " : " + e.what() + "\n"; outString (sTmp); delete HeightMap2; HeightMap1 = NULL; } } // Get all files vector<string> vAllFiles; chdir (options.InputIGDir.c_str()); dir (".ig", vAllFiles, false); chdir (sCurDir); for (uint32 i = 0; i < vAllFiles.size(); ++i) { chdir (options.InputIGDir.c_str()); CInstanceGroup *pIG = LoadInstanceGroup (vAllFiles[i].c_str()); chdir (sCurDir); if (pIG != NULL) { bool realTimeSunContribution = pIG->getRealTimeSunContribution(); // For all instances !!! CVector vGlobalPos; CInstanceGroup::TInstanceArray IA; vector<CCluster> Clusters; vector<CPortal> Portals; vector<CPointLightNamed> PLN; pIG->retrieve (vGlobalPos, IA, Clusters, Portals, PLN); if (IA.empty() && PLN.empty() && Portals.empty() && Clusters.empty()) continue; uint k; // elevate instance for(k = 0; k < IA.size(); ++k) { CVector instancePos = vGlobalPos + IA[k].Pos; IA[k].Pos.z += getHeightMapZ(instancePos.x, instancePos.y, zl, options, HeightMap1, HeightMap2); } // lights for(k = 0; k < PLN.size(); ++k) { CVector lightPos = vGlobalPos + PLN[k].getPosition(); PLN[k].setPosition( PLN[k].getPosition() + getHeightMapZ(lightPos.x, lightPos.y, zl, options, HeightMap1, HeightMap2) * CVector::K); } // portals std::vector<CVector> portal; for(k = 0; k < Portals.size(); ++k) { Portals[k].getPoly(portal); if (portal.empty()) { nlwarning("Empty portal found"); continue; } // compute mean position of the poly CVector meanPos(0, 0, 0); uint l; for(l = 0; l < portal.size(); ++l) meanPos += portal[l]; meanPos /= (float) portal.size(); meanPos += vGlobalPos; float z = getHeightMapZ(meanPos.x, meanPos.y, zl, options, HeightMap1, HeightMap2); for(l = 0; l < portal.size(); ++l) { portal[l].z += z; } Portals[k].setPoly(portal); } // clusters std::vector<CPlane> volume; CMatrix transMatrix; for(k = 0; k < Clusters.size(); ++k) { CVector clusterPos = vGlobalPos + Clusters[k].getBBox().getCenter(); float z = getHeightMapZ(clusterPos.x, clusterPos.y, zl, options, HeightMap1, HeightMap2); transMatrix.setPos(z * CVector::K); Clusters[k].applyMatrix(transMatrix); } CInstanceGroup *pIGout = new CInstanceGroup; pIGout->build (vGlobalPos, IA, Clusters, Portals, PLN); pIGout->enableRealTimeSunContribution(realTimeSunContribution); chdir (options.OutputIGDir.c_str()); SaveInstanceGroup (vAllFiles[i].c_str(), pIGout); chdir (sCurDir); delete pIG; } } return 1; }
/* * init() */ bool CPrimChecker::build(const string &primitivesPath, const string &igLandPath, const string &igVillagePath, const string &outputDirectory, bool forceRebuild) { if (Verbose) nlinfo("Checking pacs.packed_prims consistency"); NLLIGO::Register(); // Init ligo if (!LigoConfig.readPrimitiveClass ("world_editor_classes.xml", false)) { // Should be in l:\leveldesign\world_edit_files nlwarning ("Can't load ligo primitive config file world_editor_classes.xml"); return false; } uint i, j; string outputfname = CPath::standardizePath(outputDirectory)+"pacs.packed_prims"; _Grid.clear(); vector<string> files; CPath::getPathContent(primitivesPath, true, false, true, files); for (i=0; i<files.size(); ++i) { if (CFile::getExtension(files[i]) == "primitive") { readFile(files[i]); } } files.clear(); CPath::getPathContent(igLandPath, true, false, true, files); CPath::getPathContent(igVillagePath, true, false, true, files); set<string> noWaterShapes; for (i=0; i<files.size(); ++i) { try { // load ig associated to the zone string igname = files[i]; string ignamelookup = CPath::lookup(igname); //nlinfo("Reading ig '%s'", ignamelookup.c_str()); CIFile igStream(ignamelookup); CInstanceGroup ig; igStream.serial(ig); // search in group for water instance for (j=0; j<ig._InstancesInfos.size(); ++j) { string shapeName = ig._InstancesInfos[j].Name; if (CFile::getExtension (shapeName) == "") shapeName += ".shape"; if (noWaterShapes.find(shapeName) != noWaterShapes.end()) continue; string shapeNameLookup = CPath::lookup (shapeName, false, false); if (!shapeNameLookup.empty()) { CIFile f; if (f.open (shapeNameLookup)) { CShapeStream shape; shape.serial(f); CWaterShape *wshape = dynamic_cast<CWaterShape*>(shape.getShapePointer()); if (wshape == NULL) { noWaterShapes.insert(shapeName); continue; } //nlinfo("Render water shape '%s'", shapeNameLookup.c_str()); CMatrix matrix; ig.getInstanceMatrix(j, matrix); CPolygon wpoly; //wshape->getShapeInWorldSpace(wpoly); CPolygon2D wpoly2d = wshape->getShape(); uint k; for (k=0; k<wpoly2d.Vertices.size(); ++k) { wpoly.Vertices.push_back(matrix * wpoly2d.Vertices[k]); } float zwater = wpoly.Vertices[0].z - WaterThreshold; uint16 idx = (uint16)_WaterHeight.size(); _WaterHeight.push_back(zwater); render(wpoly, idx); if (Verbose) nlinfo("Rendered water shape '%s' in instance '%s'", CFile::getFilenameWithoutExtension(shapeName).c_str(), CFile::getFilenameWithoutExtension(igname).c_str()); } else if (Verbose) { noWaterShapes.insert(shapeName); nlwarning ("Can't load shape %s", shapeNameLookup.c_str()); } } else if (Verbose) { noWaterShapes.insert(shapeName); nlwarning ("Can't find shape %s", shapeName.c_str()); } } } catch (const Exception &e) { nlwarning("%s", e.what()); } } COFile f; if (f.open(outputfname)) { f.serial(_Grid); f.serialCont(_WaterHeight); } else { nlwarning("Couldn't save pacs.packed_prims file '%s'", outputfname.c_str()); } return true; }
/*********************************************************\ displayZone() \*********************************************************/ void displayZones() { const float zFarStep = 5.0f; const float tileNearStep = 10.0f; const float thresholdStep = 0.005f; ViewerCfg.TextContext.setHotSpot(CComputedString::MiddleMiddle); ViewerCfg.TextContext.setColor(CRGBA(255,255,255)); ViewerCfg.TextContext.setFontSize(20); CNELU::clearBuffers(CRGBA(0,0,0)); CNELU::swapBuffers(); // Create landscape CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Creating landscape..."); CNELU::swapBuffers(); Landscape = (CLandscapeModel*)CNELU::Scene->createModel(LandscapeModelId); Landscape->Landscape.setNoiseMode (ViewerCfg.LandscapeNoise); Landscape->Landscape.setTileNear(ViewerCfg.LandscapeTileNear); Landscape->Landscape.setThreshold(ViewerCfg.LandscapeThreshold); Landscape->Landscape.enableAutomaticLighting (ViewerCfg.AutoLight); Landscape->Landscape.setupAutomaticLightDir (ViewerCfg.LightDir); // Enable Additive Tiles. Landscape->enableAdditive(true); // HeightField. CBitmap heightBitmap; CIFile file(ViewerCfg.HeightFieldName); if( ViewerCfg.HeightFieldName!="" && heightBitmap.load(file) ) { CHeightMap heightMap; heightMap.buildFromBitmap(heightBitmap); heightMap.MaxZ= ViewerCfg.HeightFieldMaxZ; heightMap.OriginX= ViewerCfg.HeightFieldOriginX; heightMap.OriginY= ViewerCfg.HeightFieldOriginY; heightMap.SizeX = ViewerCfg.HeightFieldSizeX; heightMap.SizeY = ViewerCfg.HeightFieldSizeY; Landscape->Landscape.setHeightField(heightMap); } // Init TileBank. CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Initializing TileBanks..."); CNELU::swapBuffers(); try { CIFile bankFile (ViewerCfg.BanksPath + "/" + ViewerCfg.Bank); Landscape->Landscape.TileBank.serial(bankFile); } catch(Exception) { string tmp = string("Cant load bankfile ")+ViewerCfg.BanksPath + "/" + ViewerCfg.Bank; nlerror (tmp.c_str()); } if ((Landscape->Landscape.TileBank.getAbsPath ()=="")&&(ViewerCfg.TilesPath!="")) Landscape->Landscape.TileBank.setAbsPath (ViewerCfg.TilesPath + "/"); if (ViewerCfg.UseDDS) { Landscape->Landscape.TileBank.makeAllExtensionDDS(); } if (ViewerCfg.AllPathRelative) Landscape->Landscape.TileBank.makeAllPathRelative(); sint idx = (sint)ViewerCfg.Bank.find("."); string farBank = ViewerCfg.Bank.substr(0,idx); farBank += ".farbank"; try { CIFile farbankFile(ViewerCfg.BanksPath + "/" + farBank); Landscape->Landscape.TileFarBank.serial(farbankFile); } catch(Exception) { string tmp = string("Cant load bankfile ")+ViewerCfg.BanksPath + "/" + farBank; nlerror (tmp.c_str()); } if ( ! Landscape->Landscape.initTileBanks() ) { nlwarning( "You need to recompute bank.farbank for the far textures" ); } // Init light color CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Initializing Light..."); CNELU::swapBuffers(); Landscape->Landscape.setupStaticLight (ViewerCfg.LandDiffuse, ViewerCfg.LandAmbient, 1.1f); // Init collision manager CollisionManager.init( &(Landscape->Landscape), 200); // Preload of TileBank CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Loading TileBank..."); CNELU::swapBuffers(); for (int ts=0; ts<Landscape->Landscape.TileBank.getTileSetCount (); ts++) { CTileSet *tileSet=Landscape->Landscape.TileBank.getTileSet (ts); sint tl; for (tl=0; tl<tileSet->getNumTile128(); tl++) Landscape->Landscape.flushTiles (CNELU::Scene->getDriver(), (uint16)tileSet->getTile128(tl), 1); for (tl=0; tl<tileSet->getNumTile256(); tl++) Landscape->Landscape.flushTiles (CNELU::Scene->getDriver(), (uint16)tileSet->getTile256(tl), 1); for (tl=0; tl<CTileSet::count; tl++) Landscape->Landscape.flushTiles (CNELU::Scene->getDriver(), (uint16)tileSet->getTransition(tl)->getTile (), 1); } // Build zones. CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Loading zones..."); CNELU::swapBuffers(); uint32 i; for(i =0; i<ViewerCfg.Zones.size(); i++) { CZone zone; try { CIFile file(CPath::lookup(ViewerCfg.Zones[i])); zone.serial(file); file.close(); // Add it to landscape. Landscape->Landscape.addZone(zone); // Add it to collision manager. CollisionManager.addZone(zone.getZoneId()); } catch(Exception &e) { printf(e.what ()); } } // Load instance group. CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Loading objects..."); CNELU::swapBuffers(); for(i =0; i<ViewerCfg.Igs.size(); i++) { CInstanceGroup *group = new CInstanceGroup; try { CIFile file(CPath::lookup(ViewerCfg.Igs[i])); group->serial(file); file.close(); // Add it to the scene. group->addToScene (*CNELU::Scene); } catch(Exception &e) { printf(e.what ()); } } // Init collision Manager. CNELU::clearBuffers(CRGBA(0,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.5f,"Initializing collision manager..."); CNELU::swapBuffers(); CollisionManager.setCenter(ViewerCfg.Position); ViewerCfg.Position.z = 0.0f; CollisionManager.snapToGround( ViewerCfg.Position, 1000.0f ); // hide mouse cursor CNELU::Driver->showCursor(false); #ifdef NL_RELEASE CNELU::Driver->setCapture(true); #endif // Events management CNELU::EventServer.addEmitter(CNELU::Driver->getEventEmitter()); CNELU::AsyncListener.addToServer(CNELU::EventServer); MoveListener.init(CNELU::Scene, ViewerCfg.Width, ViewerCfg.Height, *CNELU::Camera); MoveListener.addToServer(CNELU::EventServer); MoveListener.setPos( ViewerCfg.Position ); CNELU::Camera->setPerspective (float(80.0*Pi/180.0), 1.33f, 0.1f, 1000.0f); bool showInfos = true; // initializing Z-Clip Far float left; float right; float bottom; float top; float znear; float zfar; CNELU::Camera->getFrustum(left, right, bottom, top, znear, zfar); zfar = ViewerCfg.ZFar; CNELU::Camera->setFrustum(left, right, bottom, top, znear, zfar); do { // Time mgt. //========== static sint64 t0 = (sint64)CTime::getLocalTime(); static sint64 t1 = (sint64)CTime::getLocalTime(); static sint64 ts = 0; t0 = t1; t1 = (sint64)CTime::getLocalTime(); sint64 dt64 = t1-t0; ts += dt64; float dt= ((float)dt64)*0.001f; CNELU::EventServer.pump(); // Manage movement and collision MoveListener.setLocalTime(CTime::getLocalTime()); CVector oldpos = MoveListener.getPos(); MoveListener.changeViewMatrix(); if(MoveListener.getMode()==CMoveListener::WALK) { CVector pos = MoveListener.getPos(); CollisionManager.snapToGround( pos , 1000.0f ); MoveListener.setPos( pos ); } CollisionManager.setCenter(MoveListener.getPos()); // Change move mode if(CNELU::AsyncListener.isKeyPushed(KeySPACE)) { MoveListener.swapMode(); } // Change displaying infos state if(CNELU::AsyncListener.isKeyPushed(KeyF1)) { showInfos = !showInfos; } // Change eyes height float eh = MoveListener.getEyesHeight(); if(CNELU::AsyncListener.isKeyPushed(KeyADD)) { ViewerCfg.EyesHeight.z += 0.1f; eh += 0.1f; } if(CNELU::AsyncListener.isKeyPushed(KeySUBTRACT)) { ViewerCfg.EyesHeight.z -= 0.1f; eh -= 0.1f; } if(ViewerCfg.EyesHeight.z<0.1f) ViewerCfg.EyesHeight.z = 0.1f; if(eh<0.1f) eh = 0.1f; MoveListener.setEyesHeight(eh); // Change TileNear float tileNear = Landscape->Landscape.getTileNear(); if(CNELU::AsyncListener.isKeyPushed(KeyHOME)) tileNear += tileNearStep; if(CNELU::AsyncListener.isKeyPushed(KeyEND)) tileNear -= tileNearStep; if(tileNear<0) tileNear = 0; Landscape->Landscape.setTileNear(tileNear); // Change Z-Far CNELU::Camera->getFrustum(left, right, bottom, top, znear, zfar); if(CNELU::AsyncListener.isKeyDown(KeyPRIOR)) zfar += zFarStep; if(CNELU::AsyncListener.isKeyDown(KeyNEXT)) zfar -= zFarStep; if(zfar<0) zfar = 0; CNELU::Camera->setFrustum(left, right, bottom, top, znear, zfar); // Change Threshold float threshold = Landscape->Landscape.getThreshold(); if(CNELU::AsyncListener.isKeyPushed(KeyINSERT)) threshold += thresholdStep; if(CNELU::AsyncListener.isKeyPushed(KeyDELETE)) threshold -= thresholdStep; if(threshold<0.001f) threshold = 0.001f; if(threshold>0.1f) threshold = 0.1f; Landscape->Landscape.setThreshold(threshold); // Switch between wired and filled scene display if(CNELU::AsyncListener.isKeyPushed(KeyF3)) { if (CNELU::Driver->getPolygonMode ()==IDriver::Filled) CNELU::Driver->setPolygonMode (IDriver::Line); else CNELU::Driver->setPolygonMode (IDriver::Filled); } // Switch between mouse move and keyboard-only move if(CNELU::AsyncListener.isKeyPushed(KeyRETURN)) { MoveListener.changeControlMode(); } // Render //======= CNELU::clearBuffers(ViewerCfg.Background); CNELU::Driver->clearZBuffer(); CNELU::Scene->render(); if(showInfos) { // black top quad CDRU::drawQuad(0,0.97f,1.0f,1.0f,*CNELU::Driver,CRGBA(0,0,0),CNELU::Scene->getViewport()); // black bottom quad CDRU::drawQuad(0,0,1.0f,0.03f,*CNELU::Driver,CRGBA(0,0,0),CNELU::Scene->getViewport()); ViewerCfg.TextContext.setFontSize(12); ViewerCfg.TextContext.setColor(CRGBA(255,255,255)); // Display fps. ViewerCfg.TextContext.printfAt(0.05f,0.98f,"%.1f fps",1/dt); // Display ms ViewerCfg.TextContext.printfAt(0.12f,0.98f,"%d ms",dt64); // Display Tile Near ViewerCfg.TextContext.printfAt(0.75f,0.98f,"Tile Near : %.1f",tileNear); //Display moving mode ViewerCfg.TextContext.setColor(CRGBA(255,0,0)); switch(MoveListener.getMode()) { case CMoveListener::WALK : ViewerCfg.TextContext.printfAt(0.5f,0.98f,"Walk Mode"); break; case CMoveListener::FREE : ViewerCfg.TextContext.printfAt(0.5f,0.98f,"Free-Look Mode"); break; default: break; } ViewerCfg.TextContext.setColor(CRGBA(255,255,255)); // Display Threshold ViewerCfg.TextContext.printfAt(0.3f,0.98f,"Threshold : %.3f",threshold); // Display Clip Far ViewerCfg.TextContext.printfAt(0.92f,0.98f,"Clip Far : %.1f",zfar); ViewerCfg.TextContext.setHotSpot(CComputedString::MiddleBottom); // Display current zone name CVector pos = MoveListener.getPos(); string zoneName = getZoneNameByCoord(pos.x, pos.y); ViewerCfg.TextContext.printfAt(0.3f,0.01f,"Zone : %s",zoneName.c_str()); // Position ViewerCfg.TextContext.printfAt(0.1f,0.01f,"Position : %d %d %d",(sint)pos.x,(sint)pos.y,(sint)pos.z); // Eyes height ViewerCfg.TextContext.printfAt(0.7f,0.01f,"Eyes : %.2f m",ViewerCfg.EyesHeight.z); // Display speed in km/h ViewerCfg.TextContext.setColor(CRGBA(255,0,0)); ViewerCfg.TextContext.printfAt(0.5f,0.01f,"Speed : %d km/h",(sint)(MoveListener.getSpeed()*3.6f)); ViewerCfg.TextContext.setColor(CRGBA(255,255,255)); // Heading sint heading = -(sint)(MoveListener.getRotZ()*180/Pi)%360; if(heading<0) heading += 360; ViewerCfg.TextContext.printfAt(0.9f,0.01f,"Heading : %d degrees",heading); // Display the cool compass. displayOrientation(); } CNELU::swapBuffers(); CNELU::screenshot(); } while(!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)); ViewerCfg.Position = MoveListener.getPos(); CNELU::AsyncListener.removeFromServer(CNELU::EventServer); MoveListener.removeFromServer(CNELU::EventServer); CNELU::Driver->showCursor(true); #ifdef NL_RELEASE CNELU::Driver->setCapture(false); #endif }