bool CClusterGen::StoreLineSegmentCluster() { int currClusterId = 0; for (int i = 0; i < m_currComponentId; i++) { if (m_lineSegmentClusters[i].enabled) { // store the clusters finally identified // START ... CCluster* pClusterItem = new CCluster(currClusterId, m_document->m_nDimensions); m_document->m_clusterList.push_back(pClusterItem); for (int j = 0; j < m_lineSegmentClusters[i].nClusterPoints; j++) pClusterItem->AddPointToArray(m_lineSegmentClusters[i].clusterPointArray[j]); pClusterItem->SetDensity(m_lineSegmentClusters[i].nTrajectories); pClusterItem->SetDifferentSegmentInCluster(m_lineSegmentClusters[i].nLineSegments); currClusterId++; // increase the number of final clusters // ... END } } m_document->m_nClusters = currClusterId; return true; }
ICluster * CreateCluster(const CString & url, const LogicalCluster * data) { CCluster * attr = CreateClusterRaw(url, data->Name); ATLASSERT(attr); attr->Update(data); return attr; }
int main() #endif { double rGlobalTime = 0; double rOldGlobalTime = 0; double rDeltaTime = 0; vector<SDispCS> DispCS; bool bAutoDetect = true; bool bDisplay = true; sint32 nSelected = 0; SDispCS dcsTemp; vector<CInstanceGroup*> vAllIGs; // 2 dynamics objects CTransformShape *pDynObj_InRoot; CTransformShape *pDynObj_InCS; CNELU::init (800, 600, CViewport(), 32, true); CNELU::Scene->enableLightingSystem(true); CNELU::Scene->setAmbientGlobal(CRGBA(128,128,128)); CPath::addSearchPath(CV_DIR); CPath::addSearchPath(CV_DIR"/shapes"); CPath::addSearchPath(CV_DIR"/groups"); CPath::addSearchPath(CV_DIR"/fonts"); CFontManager FontManager; CTextContext TextContext; TextContext.init (CNELU::Driver, &FontManager); TextContext.setFontGenerator (NLMISC::CPath::lookup("n019003l.pfb")); TextContext.setHotSpot (CComputedString::TopLeft); TextContext.setColor (CRGBA(255,255,255)); TextContext.setFontSize (20); CEvent3dMouseListener MouseListener; MouseListener.addToServer (CNELU::EventServer); MouseListener.setFrustrum (CNELU::Camera->getFrustum()); MouseListener.setMouseMode (CEvent3dMouseListener::firstPerson); CNELU::Camera->setTransformMode (ITransformable::DirectMatrix); // Force to automatically find the cluster system CNELU::Camera->setClusterSystem ((CInstanceGroup*)-1); CClipTrav *pClipTrav = (CClipTrav*)&(CNELU::Scene->getClipTrav()); dcsTemp.Name = "Root"; dcsTemp.pIG = NULL; DispCS.push_back (dcsTemp); // Add all instance that create the scene // -------------------------------------- // Beginning of script reading CVector CameraStart; LoadSceneScript ("main.cvs", CNELU::Scene, DispCS, CameraStart, vAllIGs); CMatrix m = MouseListener.getViewMatrix(); m.setPos (CameraStart); MouseListener.setMatrix (m); // End of script reading // Put a dynamic object in the root pDynObj_InRoot = CNELU::Scene->createInstance ("sphere01.shape"); pDynObj_InRoot->setPos (0.0f, 0.0f, 0.0f); // Put a dynamic object inside pDynObj_InCS = CNELU::Scene->createInstance ("sphere01.shape"); pDynObj_InCS->setPos (50.0f, 50.0f, 25.0f); // No automatic detection for moving objects - setup in street pDynObj_InCS->setClusterSystem (vAllIGs[0]); // Main loop do { rGlobalTime = CTime::ticksToSecond(CTime::getPerformanceTime()); rDeltaTime = rGlobalTime - rOldGlobalTime; rOldGlobalTime = rGlobalTime; pDynObj_InRoot->setPos (-20.0f+20.0f*sinf((float)rGlobalTime), -20.0f+20.0f*cosf((float)rGlobalTime*1.2f), 20.0f*sinf((float)rGlobalTime*1.1f+0.5f)); pDynObj_InCS->setPos (25.0f+5.0f*sinf((float)rGlobalTime*1.4f), -25.0f+5.0f*cosf((float)rGlobalTime*1.3f), 25.0f+2.0f*sinf((float)rGlobalTime*1.2f+0.7f)); CNELU::Scene->animate ((float)rGlobalTime); CNELU::EventServer.pump(); CNELU::clearBuffers (CRGBA(0,0,0)); CNELU::Scene->render (); // ----------------------------------------------------- // ----------------------------------------------------- if (bDisplay) { vector<CCluster*> vCluster; DispCS[0].pIG = pClipTrav->RootCluster->Group; TextContext.setColor (CRGBA(255,255,255,255)); if (bAutoDetect) { TextContext.printfAt (0, 1, "AutoDetect : ON"); pClipTrav->fullSearch (vCluster, pClipTrav->CamPos); for (uint32 i = 0; i < DispCS.size(); ++i) { TextContext.setColor (CRGBA(255,255,255,255)); for( uint32 j = 0; j < vCluster.size(); ++j) { if (DispCS[i].pIG == vCluster[j]->Group) { TextContext.setColor (CRGBA(255,0,0,255)); break; } } TextContext.printfAt (0, 1-(i+2)*0.028f, DispCS[i].Name.c_str()); } } else { TextContext.printfAt (0, 1, "AutoDetect : OFF"); CInstanceGroup *pCurIG = CNELU::Camera->getClusterSystem(); for (uint32 i = 0; i < DispCS.size(); ++i) { if (DispCS[i].pIG == pCurIG) TextContext.setColor (CRGBA(255,0,0,255)); else TextContext.setColor (CRGBA(255,255,255,255)); TextContext.printfAt (0, 1-(i+2)*0.028f, DispCS[i].Name.c_str()); } TextContext.setColor (CRGBA(255,255,255,255)); pClipTrav->Accel.select (pClipTrav->CamPos, pClipTrav->CamPos); CQuadGrid<CCluster*>::CIterator itAcc = pClipTrav->Accel.begin(); while (itAcc != pClipTrav->Accel.end()) { CCluster *pCluster = *itAcc; if (pCluster->Group == pClipTrav->Camera->getClusterSystem()) if (pCluster->isIn (pClipTrav->CamPos)) { vCluster.push_back (pCluster); } ++itAcc; } if ((vCluster.size() == 0) && (DispCS[0].pIG == pCurIG)) { vCluster.push_back (pClipTrav->RootCluster); } } TextContext.setColor (CRGBA(255,255,255,255)); string sAllClusters = ""; for( uint32 j = 0; j < vCluster.size(); ++j) { sAllClusters += vCluster[j]->Name; if (j < (vCluster.size()-1)) sAllClusters += ", "; } TextContext.printfAt (0, 1-0.028f, sAllClusters.c_str()); } // ----------------------------------------------------- // ----------------------------------------------------- CNELU::Driver->swapBuffers (); // Keys management // --------------- if (CNELU::AsyncListener.isKeyDown (KeySHIFT)) MouseListener.setSpeed (50.0f); else MouseListener.setSpeed (10.0f); CNELU::Camera->setMatrix (MouseListener.getViewMatrix()); if (CNELU::AsyncListener.isKeyPushed(KeyL)) { CNELU::Driver->setPolygonMode (IDriver::Line); } if (CNELU::AsyncListener.isKeyPushed (KeyP)) { CNELU::Driver->setPolygonMode (IDriver::Filled); } if (CNELU::AsyncListener.isKeyPushed (KeyTAB)) bDisplay = !bDisplay; if (CNELU::AsyncListener.isKeyPushed (KeyA)) { if (bAutoDetect) { bAutoDetect = false; CNELU::Camera->setClusterSystem (NULL); nSelected = 0; } else { bAutoDetect = true; CNELU::Camera->setClusterSystem ((CInstanceGroup*)-1); } } if (!bAutoDetect) { if (CNELU::AsyncListener.isKeyPushed (KeyZ)) { nSelected--; if(nSelected == -1) nSelected = (sint32)DispCS.size()-1; } if (CNELU::AsyncListener.isKeyPushed (KeyS)) { nSelected++; if(nSelected == (sint32)DispCS.size()) nSelected = 0; } CNELU::Camera->setClusterSystem (DispCS[nSelected].pIG); } } while ((!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)) && CNELU::Driver->isActive()); return EXIT_SUCCESS; }
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; }
void ClustererDBSCAN::run_cluster(Points samples) { ClusterId cid = 1; // foreach pid for (PointId pid = 0; pid < samples.size(); pid++) { // not already visited if (!_visited[pid]){ _visited[pid] = true; // get the neighbors Neighbors ne = findNeighbors(pid, _eps); // not enough support -> mark as noise if (ne.size() < _minPts) { _noise[pid] = true; } else { //else it's a core point _core[pid] = true; // Add p to current cluster CCluster c; // a new cluster c.push_back(pid); // assign pid to cluster _pointId_to_clusterId[pid]=cid; // go to neighbors for (unsigned int i = 0; i < ne.size(); i++) { PointId nPid = ne[i]; // not already visited if (!_visited[nPid]) { _visited[nPid] = true; // go to neighbors Neighbors ne1 = findNeighbors(nPid, _eps); // enough support if (ne1.size() >= _minPts) { _core[nPid] = true; // join BOOST_FOREACH(Neighbors::value_type n1, ne1) { // join neighbord ne.push_back(n1); } } } // not already assigned to a cluster if (!_pointId_to_clusterId[nPid]) { // add it to the current cluster c.push_back(nPid); _pointId_to_clusterId[nPid]=cid; } }
// *************************************************************************** CInstanceGroup *CScene::findCameraClusterSystemFromRay(CInstanceGroup *startClusterSystem, const NLMISC::CVector &startPos, NLMISC::CVector &endPos) { CInstanceGroup *resultCS= NULL; CClipTrav &clipTrav= getClipTrav(); // **** Search all cluster where the startPos is in static vector<CCluster*> vCluster; vCluster.clear(); bool bInWorld = true; clipTrav.Accel.select (startPos, startPos); CQuadGrid<CCluster*>::CIterator itAcc = clipTrav.Accel.begin(); while (itAcc != clipTrav.Accel.end()) { CCluster *pCluster = *itAcc; if( pCluster->Group == startClusterSystem && pCluster->isIn (startPos) ) { vCluster.push_back (pCluster); bInWorld = false; } ++itAcc; } if (bInWorld) { vCluster.push_back (RootCluster); } // **** Do a traverse starting from each start cluser, clipping the ray instead of the camera pyramid uint i; static vector<CCluster*> vClusterVisited; vClusterVisited.clear(); for(i=0;i<vCluster.size();i++) { vCluster[i]->cameraRayClip(startPos, endPos, vClusterVisited); } // **** From each cluster, select possible clusterSystem static vector<CInstanceGroup*> possibleClusterSystem; possibleClusterSystem.clear(); for(i=0;i<vClusterVisited.size();i++) { // select only cluster where the EndPos lies in. Important else in landscape, we'll always say // that we are in a Son Cluster. if(vClusterVisited[i]->isIn(endPos)) { CInstanceGroup *cs= vClusterVisited[i]->Group; // insert if not exist (NB: 1,2 possible clusterSystem so O(N2) is OK) uint j; for(j=0;j<possibleClusterSystem.size();j++) { if(possibleClusterSystem[j]==cs) break; } if(j==possibleClusterSystem.size()) possibleClusterSystem.push_back(cs); } } // If no cluster found, then we may be in a "Data Error case". // In this case, ensure the Camera position in a cluster if(possibleClusterSystem.empty()) { CCluster *bestCluster= NULL; float shortDist= FLT_MAX; for(i=0;i<vClusterVisited.size();i++) { // if the ray is at least partially in this cluster CVector a= startPos; CVector b= endPos; if(vClusterVisited[i]->clipSegment(a, b)) { float dist= (endPos - b).norm(); if(dist<shortDist) { bestCluster= vClusterVisited[i]; shortDist= dist; } } } // if found if(bestCluster) { // append the best one to the possible Cluster System possibleClusterSystem.push_back(bestCluster->Group); // and modify endPos, so the camera will really lies into this cluster const float threshold= 0.05f; shortDist+= threshold; // must not goes more than startPos! float rayDist= (startPos - endPos).norm(); shortDist= min(shortDist, rayDist); endPos+= (startPos - endPos).normed() * shortDist; } } // NB: still possible that the possibleClusterSystem is empty, if not in any cluster for instance :) // **** From each possible clusterSystem, select the one that is the lower in hierarchy // common case if(possibleClusterSystem.empty()) resultCS= NULL; else if(possibleClusterSystem.size()==1) { // if it is the rootCluster set NULL (should have the same behavior but do like standard case) if(possibleClusterSystem[0]==RootCluster->getClusterSystem()) resultCS= NULL; // set this cluster system else resultCS= possibleClusterSystem[0]; } // conflict case else { // compute the hierarchy level of each cluster system, take the highest CInstanceGroup *highest= NULL; uint highestLevel= 0; for(i=0;i<possibleClusterSystem.size();i++) { uint level= 0; CInstanceGroup *ig= possibleClusterSystem[i]; while(ig) { ig= ig->getParentClusterSystem(); level++; } if(level>=highestLevel) { highestLevel= level; highest= possibleClusterSystem[i]; } } // set the highest cluster system resultCS= highest; } return resultCS; }