void CZoneEdge::buildMatrix (NLMISC::CMatrix& mat, const CLigoConfig &config) const { // Build a transformation matrix mat.identity(); mat.rotateZ ((float)Pi*(float)_Rotation/2.f); mat.setPos (CVector (config.CellSize*(float)_OffsetX, config.CellSize*(float)_OffsetY, 0)); }
void CGPUProgramParams::set4x4f(const std::string &name, const NLMISC::CMatrix& m) { // TODO: Verify this! float *f = getPtrFByOffset(allocOffset(name, 4, 4, Float)); NLMISC::CMatrix mt = m; mt.transpose(); mt.get(f); }
void CGPUProgramParams::set4x4f(uint index, const NLMISC::CMatrix& m) { // TODO: Verify this! float *f = getPtrFByOffset(allocOffset(index, 4, 4, Float)); NLMISC::CMatrix mt = m; mt.transpose(); mt.get(f); }
//============================================ void CWaterShape::getShapeInWorldSpace(NLMISC::CPolygon &poly) const { poly.Vertices.resize(_Poly.Vertices.size()); // compute the matrix of the object in world space, by using the default tracks NLMISC::CMatrix objMat; objMat.identity(); objMat.translate(_DefaultPos.getDefaultValue()); objMat.rotate(_DefaultRotQuat.getDefaultValue()); objMat.scale(_DefaultScale.getDefaultValue()); for (uint k = 0; k < _Poly.Vertices.size(); ++k) { poly.Vertices[k] = objMat * NLMISC::CVector(_Poly.Vertices[k].x, _Poly.Vertices[k].y, 0); } }
//********************************************************* bool CCustomMatrix::set(bool newOn, const NLMISC::CMatrix &newMat) { if (newOn) { if (On) { float srcMatUnpacked[16]; float destMatUnpacked[16]; Matrix.get(srcMatUnpacked); newMat.get(destMatUnpacked); if (std::equal(srcMatUnpacked, srcMatUnpacked + 16, destMatUnpacked)) return false; } On = newOn; Matrix = newMat; return true; } Matrix = newMat; if (newOn != On) { On = newOn; return true; } return false; }
void updateCamera() { if (StereoHMD) { NLMISC::CQuat hmdOrient = StereoHMD->getOrientation(); NLMISC::CMatrix camMatrix = Camera.getMatrix(); NLMISC::CMatrix hmdMatrix; hmdMatrix.setRot(hmdOrient); NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future posMatrix.translate(StereoHMD->getEyePosition()); Camera.setMatrix((camMatrix * hmdMatrix) * posMatrix); } // Set the new position of the snow emitter CMatrix mat = CMatrix::Identity; mat.setPos (Camera.getMatrix().getPos()/*+CVector (0.0f, 0.0f, -10.0f)*/); Snow.setMatrix(mat); }
// *************************************************************************** void CMaterial::decompUserTexMat(uint stage, float &uTrans, float &vTrans, float &wRot, float &uScale, float &vScale) { nlassert(stage < IDRV_MAT_MAXTEXTURES); nlassert(isUserTexMatEnabled(stage)); // must activate animated texture matrix for this stage CMatrix convMat; // exported v are already inverted (todo: optim this...) convMat.setRot(CVector::I, -CVector::J, CVector::K); convMat.setPos(CVector::J); const NLMISC::CMatrix texMat = convMat * _TexUserMat->TexMat[stage] * convMat; /// find the rotation around w NLMISC::CVector i = texMat.getI(); NLMISC::CVector j = texMat.getJ(); uScale = sqrtf(i.x * i.x + j.x * j.x); vScale = sqrtf(i.y * i.y + j.y * j.y); // i.normalize(); // float angle = acosf(i.x / i.norm()); if (i.y < 0) { angle = 2.f * (float) NLMISC::Pi - angle; } wRot = angle; // compute position CMatrix InvSR; InvSR.setRot(texMat.getI(), texMat.getJ(), texMat.getK()); InvSR.invert(); CVector half(0.5f, 0.5f, 0.f); CVector offset = half + InvSR * (texMat.getPos() -half); uTrans = - offset.x; vTrans = - offset.y; }
void CVegetableEditor::update() { // Vegetable: manage collision snapping if wanted and possible if(_VegetableSnapToGround && _VegetableLandscape) { // get matrix from camera. NLMISC::CMatrix matrix = Modules::objView().getScene()->getCam().getMatrix(); // snap To ground. NLMISC::CVector pos = matrix.getPos(); // if succes to snap to ground if(_VegetableCollisionEntity->snapToGround(pos)) { pos.z+= _VegetableSnapHeight; matrix.setPos(pos); // reset the moveListener and the camera. Modules::objView().get3dMouseListener()->setMatrix(matrix); Modules::objView().getScene()->getCam().setMatrix(matrix); } } }
// *************************************************************************** void COutpost::initOutpost () { // remove the outpost from col, if any removeOutpost(); // Add collisions, if correclty setuped if (_OutpostId > -1) { // Register RZ_MAX_BUILDING_PER_OUTPOST observers for the RZ_MAX_BUILDING_PER_OUTPOST buildings uint i; for (i=0; i<RZ_MAX_BUILDING_PER_OUTPOST; i++) { // Put the ZC pacs_prim TPacsPrimMap::iterator pbIt = PacsPrims.find(NLMISC::strlwr(NLMISC::CFile::getFilenameWithoutExtension(ClientCfg.ZCPacsPrim))); if (pbIt != PacsPrims.end()) { // Build the building matrix NLMISC::CMatrix instanceMatrix; instanceMatrix.identity(); instanceMatrix.setRot(_Buildings[i].Rotation); instanceMatrix.setPos(_Buildings[i].Position); // Compute orientation and position NLMISC::CVector pos; float angle; NLPACS::UMoveContainer::getPACSCoordsFromMatrix(pos, angle, instanceMatrix); // insert the matching primitive block if (PACS) PACS->addCollisionnablePrimitiveBlock(pbIt->second, 0, 1, &_AddedPrims, angle, pos, true, CVector(1,1,1)); } } } // add 3D if needed if(_Village) _Village->initOutpost(); }
void CSoundSystem::setListenerMatrix(const NLMISC::CMatrix &m) { if (_AudioMixer) { static CMatrix oldMatrix; if(m.getPos() != oldMatrix.getPos() || m.getJ() != oldMatrix.getJ() || m.getK() != oldMatrix.getK()) { UListener *l = _AudioMixer->getListener(); l->setPos(m.getPos()); l->setOrientation(m.getJ(), m.getK()); oldMatrix = m; } } }
/** Load and compute the bbox of the models that are contained in a given instance group * \return true if the computed bbox is valid */ static void computeIGBBox(const NL3D::CInstanceGroup &ig, CLightingBBox &result, TShapeMap &shapeMap) { result = CLightingBBox(); // starts with void result bool firstBBox = true; /// now, compute the union of all bboxs for (CInstanceGroup::TInstanceArray::const_iterator it = ig._InstancesInfos.begin(); it != ig._InstancesInfos.end(); ++it) { CLightingBBox currBBox; bool validBBox = false; /// get the bbox from file or from map if (shapeMap.count(it->Name)) // already loaded ? { currBBox = shapeMap[it->Name]; validBBox = true; } else // must load the shape to get its bbox { std::string shapePathName; std::string toLoad = it->Name; if (getExt(toLoad).empty()) toLoad += ".shape"; shapePathName = NLMISC::CPath::lookup(toLoad, false, false); if (shapePathName.empty()) { nlwarning("Unable to find shape %s", it->Name.c_str()); } else { CIFile shapeInputFile; if (shapeInputFile.open (shapePathName.c_str())) { NL3D::CShapeStream shapeStream; try { shapeStream.serial (shapeInputFile); // NB Nico : // Deal with water shape -> their 'Receiving' box is set to 'void' // this prevent the case where a huge surface of water will cause the zone it is attached to (the 'Zone' // field in the villages sheets) to load all the zones that the water surface cover. (This caused // an 'out of memory error' in the zone lighter due to too many zone being loaded) // FIXME : test for water case hardcoded for now CWaterShape *ws = dynamic_cast<CWaterShape *>(shapeStream.getShapePointer()); if (ws) { CAABBox bbox; shapeStream.getShapePointer()->getAABBox(bbox); currBBox.OccludingBox = CPotentialBBox(bbox); // occluding box is used, though the water shape // doesn't cast shadow -> the tiles flag ('above', 'intersect', 'below water') // are updated inside the zone_lighter currBBox.ReceivingBox.IsVoid = true; // no lighted by the zone lighter !!! currBBox.removeVoid(); shapeMap[it->Name] = currBBox; } else { CAABBox bbox; shapeStream.getShapePointer()->getAABBox(bbox); currBBox.OccludingBox = CPotentialBBox(bbox); currBBox.ReceivingBox = CPotentialBBox(bbox); currBBox.removeVoid(); shapeMap[it->Name] = currBBox; } validBBox = true; } catch (NLMISC::Exception &e) { nlwarning("Error while loading shape %s. \n\t Reason : %s ", it->Name.c_str(), e.what()); } } else { nlwarning("Unable to open shape file %s to get its bbox", it->Name.c_str()); } } } if (validBBox) { /// build the model matrix NLMISC::CMatrix mat; mat.scale(it->Scale); NLMISC::CMatrix rotMat; rotMat.setRot(it->Rot); mat = rotMat * mat; mat.setPos(it->Pos); /// transform the bbox currBBox.transform(mat); currBBox.removeVoid(); if (firstBBox) { result = currBBox; firstBBox = false; } else // add to previous one { result.makeUnion(currBBox); } } } }
void CProgress::internalProgress (float value) { // Get croped value value = getCropedValue (value); // can't do anything if no driver if (Driver == NULL) return; if (Driver->AsyncListener.isKeyPushed (KeyDOWN)) selectTipsOfTheDay (TipsOfTheDayIndex-1); if (Driver->AsyncListener.isKeyPushed (KeyUP)) selectTipsOfTheDay (TipsOfTheDayIndex+1); // Create camera for stereo mode bool stereoHMD = StereoHMD && !MainCam.empty() && (MainCam.getTransformMode() == UCamera::RotQuat); CVector oldPos; CQuat oldQuat; if (stereoHMD) { MainCam.getPos(oldPos); MainCam.getRotQuat(oldQuat); StereoHMD->setInterfaceMatrix(CMatrix()); // identity NLMISC::CQuat hmdOrient = StereoHMD->getOrientation(); NLMISC::CMatrix camMatrix; camMatrix.identity(); NLMISC::CMatrix hmdMatrix; hmdMatrix.setRot(hmdOrient); NLMISC::CMatrix posMatrix; // minimal head modeling, will be changed in the future posMatrix.translate(StereoHMD->getEyePosition()); NLMISC::CMatrix mat = ((camMatrix * hmdMatrix) * posMatrix); MainCam.setPos(mat.getPos()); MainCam.setRotQuat(mat.getRot()); StereoDisplay->updateCamera(0, &MainCam); } uint i = 0; while ((!stereoHMD && i == 0) || (stereoHMD && StereoDisplay->nextPass())) { ++i; if (stereoHMD) { // modify cameras for stereo display const CViewport &vp = StereoDisplay->getCurrentViewport(); Driver->setViewport(vp); StereoDisplay->getCurrentMatrix(0, &MainCam); StereoDisplay->getCurrentFrustum(0, &MainCam); // begin current pass StereoDisplay->beginRenderTarget(); nldebug("Cam pos: %f, %f, %f", MainCam.getPos().x, MainCam.getPos().y, MainCam.getPos().z); } if (!stereoHMD || StereoDisplay->wantClear()) { Driver->clearBuffers(CRGBA(0, 0, 0, 0)); } if (stereoHMD && StereoDisplay->wantScene()) { Driver->setMatrixMode3D(MainCam); } if (!stereoHMD || StereoDisplay->wantInterface2D()) { // nldebug("Draw progress 2D"); // Font factor float fontFactor = 1; if (Driver->getWindowHeight() > 0) fontFactor = (float)Driver->getWindowHeight() / 600.f; fontFactor *= _FontFactor; // Set 2d view. Driver->setMatrixMode2D11(); // Display the loading background. drawLoadingBitmap(value); // temporary values for conversions float x, y, width, height; for(uint i = 0; i < ClientCfg.Logos.size(); i++) { std::vector<string> res; explode(ClientCfg.Logos[i], std::string(":"), res); if(res.size()==9 && i<LogoBitmaps.size() && LogoBitmaps[i]!=NULL) { fromString(res[1], x); fromString(res[2], y); fromString(res[3], width); fromString(res[4], height); Driver->drawBitmap(x/(float)ClientCfg.Width, y/(float)ClientCfg.Height, width/(float)ClientCfg.Width, height/(float)ClientCfg.Height, *LogoBitmaps[i]); } } if (TextContext != NULL) { // Init the Pen. TextContext->setKeep800x600Ratio(false); TextContext->setColor(CRGBA(255,255,255)); TextContext->setFontSize((uint)(12.f * fontFactor)); TextContext->setHotSpot(UTextContext::TopRight); #if !FINAL_VERSION // Display the Text. TextContext->printAt(1, 0.98f, _ProgressMessage); #else if( ClientCfg.LoadingStringCount > 0 ) { TextContext->printAt(1, 0.98f, _ProgressMessage); } #endif // FINAL_VERSION // Display the build version. TextContext->setFontSize((uint)(12.f * fontFactor)); TextContext->setHotSpot(UTextContext::TopRight); string str; #if FINAL_VERSION str = "FV "; #else str = "DEV "; #endif str += RYZOM_VERSION; TextContext->printfAt(1.0f,1.0f, str.c_str()); // Display the tips of the day. TextContext->setFontSize((uint)(16.f * fontFactor)); TextContext->setHotSpot(UTextContext::MiddleTop); ucstring::size_type index = 0; ucstring::size_type end = TipsOfTheDay.find((ucchar)'\n'); if (end == string::npos) end = TipsOfTheDay.size(); float fY = ClientCfg.TipsY; if (!TipsOfTheDay.empty()) { while (index < end) { // Get the line ucstring line = TipsOfTheDay.substr (index, end-index); // Draw the line TextContext->printAt(0.5f, fY, line); fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); index=end+1; end = TipsOfTheDay.find((ucchar)'\n', index); if (end == ucstring::npos) end = TipsOfTheDay.size(); } // More help TextContext->setFontSize((uint)(12.f * fontFactor)); /* todo tips of the day uncomment ucstring ucstr = CI18N::get ("uiTipsEnd"); TextContext->printAt(0.5f, fY, ucstr); */ fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); fY = nextLine (TextContext->getFontSize(), Driver->getWindowHeight(), fY); } if (!_TPReason.empty()) { TextContext->setHotSpot(UTextContext::MiddleMiddle); TextContext->setFontSize((uint)(14.f * fontFactor)); TextContext->printAt(0.5f, 0.5f, _TPReason); TextContext->setHotSpot(UTextContext::BottomLeft); TextContext->setColor(NLMISC::CRGBA::White); } if (!_TPCancelText.empty()) { if (ClientCfg.Width != 0 && ClientCfg.Height != 0) { TextContext->setFontSize((uint)(15.f * fontFactor)); TextContext->setHotSpot(UTextContext::BottomLeft); ucstring uc = CI18N::get("uiR2EDTPEscapeToInteruptLoading") + " (" + _TPCancelText + ") - " + CI18N::get("uiDelayedTPCancel"); UTextContext::CStringInfo info = TextContext->getStringInfo(uc); float stringX = 0.5f - info.StringWidth/(ClientCfg.Width*2); TextContext->printAt(stringX, 7.f / ClientCfg.Height, uc); } } // Teleport help //fY = ClientCfg.TeleportInfoY; if (!ApplyTextCommands && LoadingContinent && !LoadingContinent->Indoor) { TextContext->setFontSize((uint)(13.f * fontFactor)); // Print some more info uint32 day = RT.getRyzomDay(); str = toString (CI18N::get ("uiTipsTeleport").toUtf8().c_str(), CI18N::get (LoadingContinent->LocalizedName).toUtf8().c_str(), day, (uint)RT.getRyzomTime(), CI18N::get ("uiSeason"+toStringEnum(CRyzomTime::getSeasonByDay(day))).toUtf8().c_str(), CI18N::get (WeatherManager.getCurrWeatherState().LocalizedName).toUtf8().c_str()); ucstring ucstr; ucstr.fromUtf8 (str); TextContext->setHotSpot(UTextContext::MiddleBottom); TextContext->setColor(CRGBA(186, 179, 163, 255)); TextContext->printAt(0.5f, 25/768.f, ucstr); } // apply text commands if( ApplyTextCommands ) { std::vector<CClientConfig::SPrintfCommand> printfCommands = ClientCfg.PrintfCommands; if(FreeTrial) printfCommands = ClientCfg.PrintfCommandsFreeTrial; if( !printfCommands.empty() ) { TextContext->setHotSpot(UTextContext::MiddleBottom); vector<CClientConfig::SPrintfCommand>::iterator itpc; for( itpc = printfCommands.begin(); itpc != printfCommands.end(); ++itpc ) { float x = 0.5f;//((*itpc).X / 1024.f); float y = ((*itpc).Y / 768.f); TextContext->setColor( (*itpc).Color ); TextContext->setFontSize( (uint)(16.f * fontFactor)); // build the ucstr(s) ucstring ucstr = CI18N::get((*itpc).Text); vector<ucstring> vucstr; ucstring sep("\n"); splitUCString(ucstr,sep,vucstr); // Letter size UTextContext::CStringInfo si = TextContext->getStringInfo(ucstring("|")); uint fontHeight = (uint) si.StringHeight + 2; // we add 2 pixels for the gap uint i; float newy = y; for( i=0; i<vucstr.size(); ++i ) { TextContext->printAt(x,newy, vucstr[i]); newy = nextLine(fontHeight, Driver->getWindowHeight(), newy); } } } } } } if (stereoHMD) { StereoDisplay->endRenderTarget(); } } /* stereo loop */ if (stereoHMD) { MainCam.setPos(oldPos); MainCam.setRotQuat(oldQuat); } // Clamp clamp (value, 0.f, 1.f); // Set matrix Driver->setMatrixMode2D11 (); // want to receive the 'mouse down' event to deal with the 'cancel tp button' Driver->EventServer.addListener(EventMouseDownId, this); // Update messages CInputHandlerManager::getInstance()->pumpEventsNoIM(); Driver->EventServer.removeListener(EventMouseDownId, this); // Exit ? bool activeDriver = Driver->isActive(); if ((UseEscapeDuringLoading && Driver->AsyncListener.isKeyPushed (KeyESCAPE)) || !activeDriver) { // Release the application releaseMainLoop(true); release(); // Leave the application extern void quitCrashReport (); quitCrashReport (); exit(EXIT_SUCCESS); } if(!_TPCancelText.empty() && Driver->AsyncListener.isKeyPushed(KeySHIFT) && Driver->AsyncListener.isKeyPushed(KeyESCAPE)) { _TPCancelFlag = true; } CBGDownloaderAccess::getInstance().update(); // Display to screen. Driver->swapBuffers(); // \todo GUIGUI : Remove this when possible. NetMngr.update(); IngameDbMngr.flushObserverCalls(); NLGUI::CDBManager::getInstance()->flushObserverCalls(); // update system dependent progress bar static uint previousValue = 0; uint currentValue = (uint)(value*100.0f); if (currentValue != previousValue) { CSystemUtils::updateProgressBar(currentValue, 100); previousValue = currentValue; } }
//****************************************************************************************************** void CStartStopParticleSystem::goPreRender() { if (!_ActiveNode) return; NL3D::CParticleSystem *ps = _ActiveNode->getPSPointer(); sint currNumParticles = (sint) ps->getCurrNumParticles(); sint maxNumParticles = (sint) ps->getMaxNumParticles(); // if linked with scene animation, restart if animation ends if (m_LinkPlayToScenePlay) // is scene animation subordinated to the fx animation { // start animation for the scene too if (_AnimationDLG && isRunning()) { if (_LastSceneAnimFrame > _AnimationDLG->CurrentFrame) // did animation restart ? { restartAllFX(); } _LastSceneAnimFrame = _AnimationDLG->CurrentFrame; } } else if (_AutoRepeat && !m_LinkPlayToScenePlay) // auto repeat feature { if (isRunning()) { bool allFXFinished = true; bool fxStarted = false; for(uint k = 0; k < _PlayingNodes.size(); ++k) { if (_PlayingNodes[k]) { if (isRunning(_PlayingNodes[k])) { fxStarted = true; if (_PlayingNodes[k]->getPSPointer()->getSystemDate() <= _PlayingNodes[k]->getPSPointer()->evalDuration()) { allFXFinished = false; break; } else { if (_PlayingNodes[k]->getPSPointer()->getCurrNumParticles() != 0) { allFXFinished = false; break; } } } } } if (fxStarted && allFXFinished) { restartAllFX(); } } } if (_State == RunningMultiple || _State == PausedMultiple) { std::set<std::string> currAnims; CObjectViewer *ov = _ParticleDlg->getObjectViewer(); for(uint k = 0; k < ov->getNumInstance(); ++k) { CInstanceInfo *ci = ov->getInstance(k); uint animIndex = ci->Playlist.getAnimation(0); if (animIndex != NL3D::CAnimationSet::NotFound) { std::string animName = ci->AnimationSet.getAnimationName(animIndex); if (!animName.empty()) { currAnims.insert(animName); } } } // check fx that have a trigger anim for(uint k = 0; k < _PlayingNodes.size(); ++k) { if (_PlayingNodes[k]) { if (!isRunning(_PlayingNodes[k]) || !_PlayingNodes[k]->getPSModel()->hasActiveEmitters()) { // see if chosen anim is currently running if (_PlayingNodes[k]->getTriggerAnim().empty() || currAnims.count(_PlayingNodes[k]->getTriggerAnim())) { // if the fx was shutting down, stop then restart it if (!_PlayingNodes[k]->getPSModel()->hasActiveEmitters()) { nlassert(isRunning(_PlayingNodes[k])); stop(*_PlayingNodes[k]); } // yes -> trigger the fx play(*_PlayingNodes[k]); } else if (!_PlayingNodes[k]->getPSPointer()->hasParticles()) // fx is being shut down, stop it when necessary { stop(*_PlayingNodes[k]); // no more particles so stop the system } } else { if (!_PlayingNodes[k]->getTriggerAnim().empty()) { if (_PlayingNodes[k]->getPSModel()->hasActiveEmitters()) { // see if anim if already playing. If this is not the case then shutdown the emitters if (!currAnims.count(_PlayingNodes[k]->getTriggerAnim())) { _PlayingNodes[k]->getPSModel()->activateEmitters(false); } } } } } } } if (_ActiveNode) { // display number of particles for the currently active node if (currNumParticles != _LastCurrNumParticles || maxNumParticles != _LastMaxNumParticles) { CString numParts; numParts.LoadString(IDS_NUM_PARTICLES); numParts += CString(NLMISC::toString("%d / %d",(int) currNumParticles, (int) maxNumParticles).c_str()); GetDlgItem(IDC_NUM_PARTICLES)->SetWindowText((LPCTSTR) numParts); _LastCurrNumParticles = currNumParticles; _LastMaxNumParticles = maxNumParticles; } // display max number of wanted faces NLMISC::CMatrix camMat = ps->getScene()->getCam()->getMatrix(); sint numWantedFaces = (uint) ps->getWantedNumTris((ps->getSysMat().getPos() - camMat.getPos()).norm()); if (numWantedFaces != _LastNumWantedFaces) { CString numWF; numWF.LoadString(IDS_NUM_WANTED_FACES); numWF += CString(NLMISC::toString("%d",(int) numWantedFaces).c_str()); GetDlgItem(IDC_NUM_ASKED_FACES)->SetWindowText((LPCTSTR) numWF); _LastNumWantedFaces = numWantedFaces; } // display system date if (ps->getSystemDate() != _LastSystemDate) { _LastSystemDate = ps->getSystemDate(); CString sysDate; sysDate.LoadString(IDS_SYSTEM_DATE); sysDate += CString(NLMISC::toString("%.2f s",_LastSystemDate).c_str()); GetDlgItem(IDC_SYSTEM_DATE)->SetWindowText((LPCTSTR) sysDate); } } if (_ParticleDlg) { CParticleWorkspace *pws = _ParticleDlg->getParticleWorkspace(); if (pws) { for(uint k = 0; k < pws->getNumNode(); ++k) { if (pws->getNode(k)->isLoaded()) { if (pws->getNode(k) == _ActiveNode) { pws->getNode(k)->getPSModel()->enableDisplayTools(!isRunning(pws->getNode(k)) || m_DisplayHelpers); } else { pws->getNode(k)->getPSModel()->enableDisplayTools(false); } // hide / show the node if (_State == RunningMultiple || _State == PausedMultiple) { if (isRunning(pws->getNode(k))) { pws->getNode(k)->getPSModel()->show(); } else { pws->getNode(k)->getPSModel()->hide(); } } else { if (pws->getNode(k) == _ActiveNode) { pws->getNode(k)->getPSModel()->show(); } else { pws->getNode(k)->getPSModel()->hide(); } } } } } } }
// *************************************************************************** void CVisualCollisionMesh::receiveShadowMap(const NLMISC::CMatrix &instanceMatrix, const CShadowContext &shadowContext) { // empty mesh => no op if(_Vertices.empty()) return; // The VertexBuffer RefPtr has been released? quit if(_VertexBuffer == NULL) return; // **** Select triangles to be rendered with quadGrid // select with quadGrid local in mesh CAABBox localBB; localBB= CAABBox::transformAABBox(instanceMatrix.inverted(), shadowContext.ShadowWorldBB); static std::vector<uint16> triInQuadGrid; uint numTrisInQuadGrid= _QuadGrid.select(localBB, triInQuadGrid); // no intersection at all? quit if(numTrisInQuadGrid==0) return; // **** prepare more precise Clip with shadow pyramid // enlarge temp flag array static std::vector<uint8> vertexFlags; if(vertexFlags.size()<_Vertices.size()) vertexFlags.resize(_Vertices.size()); // reset all to 0 memset(&vertexFlags[0], 0, _Vertices.size()*sizeof(uint8)); // Compute the "LocalToInstance" shadow Clip Volume static std::vector<CPlane> localClipPlanes; /* We want to apply to plane this matrix: IM-1 * MCasterPos, where IM=instanceMatrix and MCasterPos= matrix translation of "shadowContext.CasterPos" BUT, since to transform a plane, we must do plane * M-1, then compute this matrix: localMat= MCasterPos-1 * IM */ CMatrix localMat; localMat.setPos(-shadowContext.CasterPos); localMat*= instanceMatrix; // Allow max bits of planes clip. localClipPlanes.resize(min((uint)shadowContext.ShadowMap->LocalClipPlanes.size(), (uint)NL3D_VCM_SHADOW_NUM_CLIP_PLANE)); // Transform into Mesh local space for(uint i=0;i<localClipPlanes.size();i++) { localClipPlanes[i]= shadowContext.ShadowMap->LocalClipPlanes[i] * localMat; } // **** Clip and fill the triangles uint currentTriIdx= 0; // enlarge the index buffer as max of triangles possibly intersected shadowContext.IndexBuffer.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT); if(shadowContext.IndexBuffer.getNumIndexes()<numTrisInQuadGrid*3) shadowContext.IndexBuffer.setNumIndexes(numTrisInQuadGrid*3); // Start to clip and fill { CIndexBufferReadWrite iba; shadowContext.IndexBuffer.lock(iba); if (iba.getFormat() == CIndexBuffer::Indices32) { uint32 *ibPtr= (uint32 *) iba.getPtr(); // for all triangles selected with the quadgrid for(uint triq=0; triq<numTrisInQuadGrid;triq++) { uint triId[3]; triId[0]= _Triangles[uint(triInQuadGrid[triq])*3+0]; triId[1]= _Triangles[uint(triInQuadGrid[triq])*3+1]; triId[2]= _Triangles[uint(triInQuadGrid[triq])*3+2]; uint triFlag= NL3D_VCM_SHADOW_NUM_CLIP_PLANE_MASK; // for all vertices, clip them for(uint i=0;i<3;i++) { uint vid= triId[i]; uint vf= vertexFlags[vid]; // if this vertex is still not computed if(!vf) { // For all planes of the Clip Volume, clip this vertex. for(uint j=0;j<localClipPlanes.size();j++) { // out if in front bool out= localClipPlanes[j]*_Vertices[vid] > 0; vf|= ((uint)out)<<j; } // add the bit flag to say "computed". vf|= NL3D_VCM_SHADOW_NUM_CLIP_PLANE_SHIFT; // store vertexFlags[vid]= vf; } // And all vertex bits. triFlag&= vf; } // if triangle not clipped, add the triangle if( (triFlag & NL3D_VCM_SHADOW_NUM_CLIP_PLANE_MASK)==0 ) { // Add the 3 index to the index buffer. ibPtr[currentTriIdx++]= triId[0]; ibPtr[currentTriIdx++]= triId[1]; ibPtr[currentTriIdx++]= triId[2]; } } } else { nlassert(iba.getFormat() == CIndexBuffer::Indices16); uint16 *ibPtr= (uint16 *) iba.getPtr(); // for all triangles selected with the quadgrid for(uint triq=0; triq<numTrisInQuadGrid;triq++) { uint triId[3]; triId[0]= _Triangles[uint(triInQuadGrid[triq])*3+0]; triId[1]= _Triangles[uint(triInQuadGrid[triq])*3+1]; triId[2]= _Triangles[uint(triInQuadGrid[triq])*3+2]; uint triFlag= NL3D_VCM_SHADOW_NUM_CLIP_PLANE_MASK; // for all vertices, clip them for(uint i=0;i<3;i++) { uint vid= triId[i]; uint vf= vertexFlags[vid]; // if this vertex is still not computed if(!vf) { // For all planes of the Clip Volume, clip this vertex. for(uint j=0;j<localClipPlanes.size();j++) { // out if in front bool out= localClipPlanes[j]*_Vertices[vid] > 0; vf|= ((uint)out)<<j; } // add the bit flag to say "computed". vf|= NL3D_VCM_SHADOW_NUM_CLIP_PLANE_SHIFT; // store vertexFlags[vid]= vf; } // And all vertex bits. triFlag&= vf; } // if triangle not clipped, add the triangle // if( (triFlag & NL3D_VCM_SHADOW_NUM_CLIP_PLANE_MASK)==0 ) if (triFlag == 0) // previous line not useful due to init { // Add the 3 index to the index buffer. ibPtr[currentTriIdx++]= (uint16) triId[0]; ibPtr[currentTriIdx++]= (uint16) triId[1]; ibPtr[currentTriIdx++]= (uint16) triId[2]; } } } } // **** Render // if some triangle to render if(currentTriIdx) { IDriver *drv= shadowContext.Driver; // setup the collision instance matrix drv->setupModelMatrix(instanceMatrix); // update the material projection matrix, cause matrix changed shadowContext.ShadowMapProjector.applyToMaterial(instanceMatrix, shadowContext.ShadowMaterial); // render drv->activeVertexBuffer(*_VertexBuffer); drv->activeIndexBuffer(shadowContext.IndexBuffer); drv->renderTriangles(shadowContext.ShadowMaterial, 0, currentTriIdx/3); // TestYoyo. Show in Red triangles selected /*if(TESTYOYO_VCM_RedShadow) { static CMaterial tam; tam.initUnlit(); tam.setColor(CRGBA(255,0,0,128)); tam.setZFunc(CMaterial::always); tam.setZWrite(false); tam.setBlend(true); tam.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha); tam.setDoubleSided(true); drv->renderTriangles(tam, 0, currentTriIdx/3); }*/ } }
// *************************************************************************** void CVegetable::generateInstance(CVegetableInstanceGroup *ig, const NLMISC::CMatrix &posInWorld, const NLMISC::CRGBAF &modulateAmbientColor, const NLMISC::CRGBAF &modulateDiffuseColor, float blendDistMax, TVegetableWater vegetWaterState, CVegetableUV8 dlmUV) const { nlassert(_Manager); CVector seed= posInWorld.getPos(); // Generate Matrix. // =============== // Generate a random Scale / Rotation matrix. CMatrix randomMat; // setup rotation CVector rot; rot.x= Rx.eval(seed); rot.y= Ry.eval(seed); rot.z= Rz.eval(seed); randomMat.setRot(rot, CMatrix::ZXY); // scale. if(Sxy.Abs!=0 || Sxy.Rand!=0 || Sz.Abs!=0 || Sz.Rand!=0) { CVector scale; scale.x= scale.y= Sxy.eval(seed); scale.z= Sz.eval(seed); randomMat.scale(scale); } // Final Matrix. CMatrix finalMatrix; finalMatrix= posInWorld * randomMat; // Generate Color and factor // =============== CRGBAF materialColor(1,1,1,1); // evaluate gradients. If none, color not modified. Color.eval(seed, materialColor); // modulate with user CRGBAF ambient, diffuse; if(_VegetableShape && _VegetableShape->Lighted) { ambient= modulateAmbientColor * materialColor; diffuse= modulateDiffuseColor * materialColor; } else { ambient= materialColor; diffuse= materialColor; } // Generate a bendFactor float bendFactor= BendFactor.eval(seed); // Generate a bendPhase float bendPhase= BendPhase.eval(seed); // Append to the vegetableManager // =============== if (_VegetableShape) { _Manager->addInstance(ig, _VegetableShape, finalMatrix, ambient, diffuse, bendFactor, bendPhase, BendFrequencyFactor, blendDistMax, (CVegetableManager::TVegetableWater)vegetWaterState, dlmUV); } }