// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/> // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "object.h" // Pacs includes #include <nel/pacs/u_move_container.h> #include <nel/pacs/u_move_primitive.h> // Misc includes #include <nel/misc/vectord.h> #include <nel/misc/quat.h> #include <nel/misc/path.h> // 3d includes #include <nel/3d/u_scene.h> #include <nel/3d/u_instance.h> #include <nel/3d/u_instance_material.h> #define BRAKE_FORCE (-0.1) // (m.s-2) #define GRAVITY_FORCE (-15.0) #define SHOCK_ABSORB (1.0) // using namespace NL3D; using namespace NLNET; using namespace NLMISC; using namespace NLPACS; // *************************************************************************** CObjectDyn::CObjectDyn (double width, double depth, double height, double orientation, const CVectorD& pos, const CVectorD& speed, bool obstacle, UMoveContainer &container, UScene &scene, UMovePrimitive::TReaction reaction, NLPACS::UMovePrimitive::TTrigger trigger, uint8 worldImage, uint8 nbImage, uint8 insertWorldImage) { // Create a box instance _Instance = scene.createInstance(CPath::lookup("rectangle.shape")); if(_Instance.empty()) { nlerror("Failed to load shape: %s", CPath::lookup("rectangle.shape").c_str()); } // Freezed Freezed = reaction == UMovePrimitive::DoNothing; // Setup the instance if (_Instance.getNumMaterials()) { uint i; for (i=0; i<_Instance.getNumMaterials(); i++) { UInstanceMaterial material = _Instance.getMaterial(i); if (trigger != UMovePrimitive::NotATrigger) { // material.setBlend(true); // material.setBlendFunc(UInstanceMaterial::srcalpha, UInstanceMaterial::invsrcalpha); material.setDiffuse (CRGBA(255,255,255,255)); // material.setOpacity(128); } else { if (Freezed) { material.setDiffuse (CRGBA(128,0,0,255)); material.setOpacity(255); } else { } } } } // Setup the instance _Instance.setScale (CVectorD (width, depth, height)); _Instance.setRotQuat (CQuat (CVectorD (0, 0, 1), (float)orientation)); // Create a collision volume _MovePrimitive = container.addCollisionablePrimitive (worldImage, nbImage); _MovePrimitive->insertInWorldImage (insertWorldImage); // Setup the collision primitive _MovePrimitive->setPrimitiveType (UMovePrimitive::_2DOrientedBox); _MovePrimitive->setHeight ((float)height); _MovePrimitive->setOrientation (orientation, insertWorldImage); _MovePrimitive->setSize ((float)width, (float)depth); // This primitive is an obstacle (it blocks others) _MovePrimitive->setObstacle (obstacle); // Setup reaction type _MovePrimitive->setReactionType (reaction); // Setup absorption value _MovePrimitive->setAbsorbtion (0.9f); // Setup user data _MovePrimitive->UserData=(uint64)this; // Setup trigger type _MovePrimitive->setTriggerType (trigger); // Set pos and speed setPos (pos); setSpeed (speed); _MovePrimitive->setGlobalPosition (pos, insertWorldImage); } // *************************************************************************** CObjectDyn::CObjectDyn (double diameter, double height, const CVectorD& pos, const CVectorD& speed, bool obstacle, UMoveContainer &container, UScene &scene, UMovePrimitive::TReaction reaction, NLPACS::UMovePrimitive::TTrigger trigger, uint8 worldImage, uint8 nbImage, uint8 insertWorldImage) { // Create a box instance _Instance = scene.createInstance(CPath::lookup("cylinder.shape")); if(_Instance.empty()) { nlerror("Failed to load shape: %s",CPath::lookup("cylinder.shape").c_str()); } // Freezed Freezed = reaction == UMovePrimitive::DoNothing; // Setup the instance if (_Instance.getNumMaterials()) { uint i; for (i=0; i<_Instance.getNumMaterials(); i++) { UInstanceMaterial material = _Instance.getMaterial(i); if (trigger != UMovePrimitive::NotATrigger) { // material.setBlend(true); // material.setBlendFunc(UInstanceMaterial::srcalpha, UInstanceMaterial::invsrcalpha); material.setDiffuse (CRGBA(255,255,255)); // material.setOpacity(128); } else { if (Freezed) { material.setDiffuse (CRGBA(128,0,0)); material.setOpacity(255); } else { } } } } // Setup the instance _Instance.setScale (CVectorD (diameter, diameter, height)); // Create a collision volume _MovePrimitive = container.addCollisionablePrimitive (worldImage, nbImage); _MovePrimitive->insertInWorldImage (insertWorldImage); // Setup the primitive _MovePrimitive->setPrimitiveType (UMovePrimitive::_2DOrientedCylinder); _MovePrimitive->setHeight ((float)height); _MovePrimitive->setRadius ((float)diameter/2.f); // This primitive is an obstacle (it blocks others) _MovePrimitive->setObstacle (obstacle); // Setup reaction type _MovePrimitive->setReactionType (reaction); // Setup reaction type _MovePrimitive->setAbsorbtion (0.9f); // Setup user data _MovePrimitive->UserData=(uint64)this; // Setup trigger type _MovePrimitive->setTriggerType (trigger); // Set pos and speed setPos (pos); setSpeed (speed); _MovePrimitive->setGlobalPosition (pos, insertWorldImage); } // *************************************************************************** void CObjectDyn::tryMove (double deltaTime, UMoveContainer &container, uint8 worldImage) { // New speed if ( (_MovePrimitive->getSpeed(worldImage).norm()>0.f) || _Speed.norm()>0.f ) { // Brake CVectorD newSpeed=_Speed; newSpeed.normalize(); newSpeed*=BRAKE_FORCE*deltaTime; newSpeed+=_Speed; // Stop ? if (_Speed*newSpeed<=0) newSpeed=CVectorD (0,0,0); // Set speed setSpeed (newSpeed); // Try this move _MovePrimitive->move (_Speed, worldImage); _TryMove=true; } else _TryMove=false; } // *************************************************************************** void CObjectDyn::doMove (double deltaTime, uint8 worldImage) { // New speed setSpeed (_MovePrimitive->getSpeed(worldImage)); // New position setPos (_MovePrimitive->getFinalPosition (worldImage)); } // *************************************************************************** void CObjectDyn::setPos (const CVectorD& pos) { _Position=pos; if (!_Instance.empty()) _Instance.setPos (pos); } // *************************************************************************** void CObjectDyn::setGlobalPos (UGlobalPosition& gpos, CVectorD& pos, uint8 worldimage) { // Place the primitive the first time _MovePrimitive->setGlobalPosition (gpos, worldimage); setPos (pos); } // *************************************************************************** void CObjectDyn::setSpeed (const CVectorD& speed) { _Speed=speed; } // *************************************************************************** void CObjectDyn::remove (NLPACS::UMoveContainer &container, UScene &scene) { // Remove from container container.removePrimitive (_MovePrimitive); // Remove instance if (!_Instance.empty()) scene.deleteInstance (_Instance); } // ***************************************************************************