Example #1
0
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));
}
Example #2
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);
}
Example #3
0
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);
}
Example #4
0
//============================================
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);
	}
}
Example #5
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;
}
Example #6
0
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);
}
Example #7
0
// ***************************************************************************
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;
}
Example #8
0
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);
		}
	}
}
Example #9
0
// ***************************************************************************
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);
			}			
		}		
	}	
}
Example #12
0
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);
		}*/
	}
}
Example #15
0
// ***************************************************************************
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);
	}
}