mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-13 21:34:48 +00:00
498 lines
14 KiB
C++
498 lines
14 KiB
C++
// 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/>.
|
|
|
|
#ifndef NL_PRIMITIVE_WORLD_IMAGE_H
|
|
#define NL_PRIMITIVE_WORLD_IMAGE_H
|
|
|
|
#include "nel/misc/types_nl.h"
|
|
|
|
#include "move_container.h"
|
|
|
|
|
|
namespace NLPACS {
|
|
|
|
|
|
/**
|
|
* Data for the primitive duplicated for each world image it is linked
|
|
* \author Cyril 'Hulud' Corvazier
|
|
* \author Nevrax France
|
|
* \date 2001
|
|
*/
|
|
class CPrimitiveWorldImage
|
|
{
|
|
public:
|
|
|
|
// Constructor
|
|
CPrimitiveWorldImage ();
|
|
|
|
// To call before destruction
|
|
void deleteIt (CMoveContainer &container, uint8 worldImage);
|
|
|
|
// Copy
|
|
void copy (const CPrimitiveWorldImage& source);
|
|
|
|
/**
|
|
* Set the global position of the move primitive.
|
|
*
|
|
* \param pos is the new global position of the primitive.
|
|
*/
|
|
void setGlobalPosition (const UGlobalPosition& pos, CMoveContainer& container, CMovePrimitive &primitive, uint8 worldImage);
|
|
|
|
/**
|
|
* Set the global position of the move primitive. Setting the global position
|
|
* can take a long time if you use a UGlobalRetriever. Set the position with
|
|
* this method only the first time or for teleporting.
|
|
*
|
|
* \param pos is the new global position of the primitive.
|
|
*/
|
|
void setGlobalPosition (const NLMISC::CVectorD& pos, CMoveContainer& container, CMovePrimitive &primitive,
|
|
uint8 worldImage, bool keepZ = false, UGlobalPosition::TType type = UGlobalPosition::Unspecified);
|
|
|
|
/**
|
|
* Get the position of the move primitive at the end of the movement.
|
|
*
|
|
* \return the new position of the primitive.
|
|
*/
|
|
NLMISC::CVectorD getFinalPosition () const
|
|
{
|
|
// Get the position
|
|
return _Position.getPos();
|
|
}
|
|
|
|
/**
|
|
* Set the new orientation of the move primitive. Only for the box primitives.
|
|
*
|
|
* \param rot is the new OZ rotation in radian.
|
|
*/
|
|
void setOrientation (double rot, CMoveContainer *container, CMovePrimitive *primitive, uint8 worldImage)
|
|
{
|
|
// New position
|
|
_OBData.Orientation=rot;
|
|
|
|
// Position has changed
|
|
dirtPos (container, primitive, worldImage);
|
|
}
|
|
|
|
/**
|
|
* Set the speed vector for this primitive. Only for movable primitives.
|
|
*
|
|
* \param speed is the speed of the primitive.
|
|
*/
|
|
void move (const NLMISC::CVectorD& speed, CMoveContainer& container, CMovePrimitive &primitive,
|
|
uint8 worldImage);
|
|
|
|
/**
|
|
* Set the speed vector for this primitive.
|
|
*
|
|
* \param speed is the new speed vector.
|
|
*/
|
|
void setSpeed (const NLMISC::CVectorD& speed, CMoveContainer *container, CMovePrimitive *primitive, uint8 worldImage)
|
|
{
|
|
// New time
|
|
_Speed=speed;
|
|
|
|
// Speed has changed
|
|
dirtPos (container, primitive, worldImage);
|
|
}
|
|
|
|
/**
|
|
* Get the speed vector for this primitive.
|
|
*
|
|
* \Return the new speed vector.
|
|
*/
|
|
const NLMISC::CVectorD& getSpeed () const
|
|
{
|
|
// New time
|
|
return _Speed;
|
|
}
|
|
|
|
/// Is in modified list ?
|
|
bool isInModifiedListFlag ()
|
|
{
|
|
return (_DynamicFlags&InModifiedListFlag) != 0;
|
|
}
|
|
|
|
/// Clear the inModifiedList flag.
|
|
void setInModifiedListFlag (bool itis)
|
|
{
|
|
if (itis)
|
|
_DynamicFlags|=InModifiedListFlag;
|
|
else
|
|
_DynamicFlags&=~InModifiedListFlag;
|
|
}
|
|
|
|
// Link into modified list
|
|
void linkInModifiedList (CMovePrimitive* next)
|
|
{
|
|
_NextModified=next;
|
|
}
|
|
|
|
/// Is in modified list ?
|
|
bool isInWorldImageFlag ()
|
|
{
|
|
return (_DynamicFlags&InWorldImageFlag) != 0;
|
|
}
|
|
|
|
/// Clear the inModifiedList flag.
|
|
void setInWorldImageFlag (bool itis)
|
|
{
|
|
if (itis)
|
|
_DynamicFlags|=InWorldImageFlag;
|
|
else
|
|
_DynamicFlags&=~InWorldImageFlag;
|
|
}
|
|
|
|
/// Get next modified primitive
|
|
CMovePrimitive *getNextModified () const
|
|
{
|
|
return _NextModified;
|
|
}
|
|
|
|
/**
|
|
* Return min of the bounding box in X.
|
|
*/
|
|
double getBBXMin () const
|
|
{
|
|
return _BBXMin;
|
|
}
|
|
|
|
/**
|
|
* Return min of the bounding box in Y.
|
|
*/
|
|
double getBBYMin () const
|
|
{
|
|
return _BBYMin;
|
|
}
|
|
|
|
/**
|
|
* Return max of the bounding box in X.
|
|
*/
|
|
double getBBXMax () const
|
|
{
|
|
return _BBXMax;
|
|
}
|
|
|
|
/**
|
|
* Return max of the bounding box in Y.
|
|
*/
|
|
double getBBYMax () const
|
|
{
|
|
return _BBYMax;
|
|
}
|
|
|
|
/**
|
|
* Return the delta position
|
|
*/
|
|
const NLMISC::CVectorD& getDeltaPosition () const
|
|
{
|
|
return _DeltaPosition;
|
|
}
|
|
|
|
/// Return the nieme MoveElement. The primitive can have 4 move elements. Can be NULL if the ineme elment is not in a list
|
|
CMoveElement *getMoveElement (uint i)
|
|
{
|
|
return _MoveElement[i];
|
|
}
|
|
|
|
/// Remove the nieme MoveElement.
|
|
void removeMoveElement (uint i, CMoveContainer &container, uint8 worldImage);
|
|
|
|
/// Add the primitive in the cell and resort the list.
|
|
void addMoveElement (CMoveCell& cell, uint16 x, uint16 y, double centerX, double centerY, CMovePrimitive *primitive,
|
|
CMoveContainer &container, uint8 worldImage);
|
|
|
|
/// Add the primitive in the cell at the end of the list and don't sort
|
|
void addMoveElementendOfList (CMoveCell& cell, uint16 x, uint16 y, CMovePrimitive *primitive,
|
|
CMoveContainer &container);
|
|
|
|
/// Update precalculated data
|
|
void update (double beginTime, double endTime, CMovePrimitive &primitive)
|
|
{
|
|
// Pos dirt ?
|
|
if (_DynamicFlags&DirtPosFlag)
|
|
{
|
|
// Compute precalculated data
|
|
precalcPos (primitive);
|
|
|
|
// Clean
|
|
_DynamicFlags&=~DirtPosFlag;
|
|
}
|
|
|
|
// Bounding box dirt ?
|
|
if (_DynamicFlags&DirtBBFlag)
|
|
{
|
|
// Compute precalculated data
|
|
precalcBB (beginTime, endTime, primitive);
|
|
|
|
// Clean
|
|
_DynamicFlags&=~DirtBBFlag;
|
|
}
|
|
}
|
|
|
|
/// Check sorted lists
|
|
void checkSortedList (uint8 worldImage);
|
|
|
|
// Return the global position of the primitive
|
|
const UGlobalPosition& getGlobalPosition()
|
|
{
|
|
return _Position.getGlobalPos();
|
|
}
|
|
|
|
// Return the orientation
|
|
double getOrientation () const
|
|
{
|
|
return _OBData.Orientation;
|
|
}
|
|
|
|
// Dirt the position flag. Position has changed.
|
|
void dirtPos (CMoveContainer *container, CMovePrimitive *primitive, uint8 worldImage)
|
|
{
|
|
_DynamicFlags|=DirtPosFlag;
|
|
dirtBB (container, primitive, worldImage);
|
|
}
|
|
|
|
// Dirt the bounding box flag.
|
|
void dirtBB (CMoveContainer *container, CMovePrimitive *primitive, uint8 worldImage)
|
|
{
|
|
// Warn container that BB has changed
|
|
container->changed (primitive, worldImage);
|
|
|
|
_DynamicFlags|=DirtBBFlag;
|
|
}
|
|
|
|
// Return the init time
|
|
double getInitTime() const
|
|
{
|
|
return _InitTime;
|
|
}
|
|
|
|
// Compute precalculated data for the position
|
|
void precalcPos (CMovePrimitive &primitive);
|
|
|
|
// Compute precalculated data for the speed
|
|
void precalcSpeed ();
|
|
|
|
// Compute precalculated bounding box
|
|
void precalcBB (double beginTime, double endTime, CMovePrimitive &primitive);
|
|
|
|
// *** Some methods to eval collisions
|
|
/* * NOTES: BB for bounding box
|
|
OB for oriented Box
|
|
OC for oriented cylinder
|
|
P for box point
|
|
S for box segment
|
|
*/
|
|
|
|
/**
|
|
* Eval collisions with the other primitive.
|
|
*
|
|
* \param other is another move primitive to test collisions with.
|
|
* \param desc is a collision descriptor filled with information
|
|
* about the collision context if the method return true.
|
|
* \param timeMin is the time you want to clip collision result in the past.
|
|
* \param timeMax is the time you want to clip collision result in the futur.
|
|
*
|
|
* \return true if a collision has been detected in the time range, else false.
|
|
*/
|
|
bool evalCollision (CPrimitiveWorldImage& other, class CCollisionDesc& desc, double timeMin,
|
|
double timeMax, uint32 testTime, uint32 maxTestIteration,
|
|
double &firstContactTime, double &lastContactTime,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
// Box over box
|
|
bool evalCollisionOBoverOB (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin,
|
|
double timeMax, double &firstContactTime, double &lastContactTime,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
// Box over cylinder
|
|
bool evalCollisionOBoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin,
|
|
double timeMax, double &firstContactTime, double &lastContactTime,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
// Cylinder over cylinder
|
|
bool evalCollisionOCoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, double timeMin,
|
|
double timeMax, double &firstContactTime, double &lastContactTime,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
// *** Subprimitive over subprimitive
|
|
|
|
// Point over segment in OB/OB test
|
|
bool evalCollisionPoverS (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numPoint, uint numSeg,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
// Point over cylinder
|
|
bool evalCollisionPoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numPoint,
|
|
double &firstContactTime, double &lastContactTime, CMovePrimitive& primitive,
|
|
CMovePrimitive& otherPrimitive);
|
|
|
|
// Segment over cylinder
|
|
bool evalCollisionSoverOC (CPrimitiveWorldImage& other, CCollisionDesc& desc, uint numPoint,
|
|
CMovePrimitive& primitive, CMovePrimitive& otherPrimitive);
|
|
|
|
/**
|
|
* Eval collisions with the global retriever.
|
|
*
|
|
* \param retriever is the global retriever used to test collision
|
|
*
|
|
* \return true if a collision has been detected in the time range, else false.
|
|
*/
|
|
const TCollisionSurfaceDescVector *evalCollision (CGlobalRetriever &retriever, CCollisionSurfaceTemp& surfaceTemp,
|
|
uint32 testTime, uint32 maxTestIteration, CMovePrimitive& primitive);
|
|
|
|
// Make a move with globalRetriever. Must be call after a free collision evalCollision call.
|
|
void doMove (CGlobalRetriever &retriever, CCollisionSurfaceTemp& surfaceTemp, double originalMax, double finalMax, bool keepZ = false);
|
|
|
|
// Make a move wihtout globalRetriever.
|
|
void doMove (double timeMax);
|
|
|
|
// Reaction between two primitives. Return true if one object has been modified.
|
|
void reaction (CPrimitiveWorldImage& second, const CCollisionDesc& desc, CGlobalRetriever* retriver,
|
|
CCollisionSurfaceTemp& surfaceTemp, bool collision, CMovePrimitive &primitive,
|
|
CMovePrimitive &otherPrimitive, CMoveContainer *container, uint8 worldImage,
|
|
uint8 secondWorldImage, bool secondConst);
|
|
|
|
// Reaction with a static collision. Return true if one object has been modified.
|
|
void reaction ( const CCollisionSurfaceDesc& surfaceDesc, const UGlobalPosition& globalPosition,
|
|
CGlobalRetriever& retriever, double ratio, double dt, CMovePrimitive &primitive, CMoveContainer &container,
|
|
uint8 worldImage);
|
|
|
|
private:
|
|
// Some flags
|
|
enum TDynamicFlags
|
|
{
|
|
// The dirt flag. Precalculated data for the position must be recomputed.
|
|
DirtPosFlag =0x0001,
|
|
|
|
// The dirt bounding box. Precalculated data for the bounding box must be recomputed.
|
|
DirtBBFlag =0x0002,
|
|
|
|
// In modified list.
|
|
InModifiedListFlag =0x0004,
|
|
|
|
// Inserted in the world image.
|
|
InWorldImageFlag =0x0008,
|
|
|
|
// Force the size to uint16.
|
|
ForceSize =0xffff
|
|
};
|
|
|
|
// Flags
|
|
uint16 _DynamicFlags;
|
|
|
|
// This position is the central bottom position for the box or for the cylinder
|
|
class CPosition
|
|
{
|
|
private:
|
|
// 3d position
|
|
NLMISC::CVectorD _3dPosition;
|
|
|
|
// Global position
|
|
UGlobalPosition _GlobalPosition;
|
|
public:
|
|
// Return the 3d position
|
|
const NLMISC::CVectorD& getPos () const
|
|
{
|
|
return _3dPosition;
|
|
}
|
|
|
|
// Set the 3d position
|
|
void setPos (const NLMISC::CVectorD& newPos)
|
|
{
|
|
_3dPosition=newPos;
|
|
}
|
|
|
|
// Return the global position
|
|
const UGlobalPosition& getGlobalPos () const
|
|
{
|
|
return _GlobalPosition;
|
|
}
|
|
|
|
// Set the global position
|
|
void setGlobalPos (const UGlobalPosition& globalPosition,
|
|
CGlobalRetriever& globalRetriver)
|
|
{
|
|
// Get position with global position
|
|
_GlobalPosition=globalPosition;
|
|
_GlobalPosition.LocalPosition.Estimation.z = globalRetriver.getMeanHeight(globalPosition);
|
|
_3dPosition=globalRetriver.getDoubleGlobalPosition (_GlobalPosition);
|
|
// _3dPosition.z=(double)globalRetriver.getMeanHeight(globalPosition);
|
|
}
|
|
|
|
void setGlobalPosKeepZ(const UGlobalPosition& globalPosition,
|
|
CGlobalRetriever& globalRetriver)
|
|
{
|
|
_GlobalPosition.setKeepZ(globalPosition);
|
|
NLMISC::CVectorD dPos = globalRetriver.getDoubleGlobalPosition (globalPosition);
|
|
_3dPosition.x = dPos.x;
|
|
_3dPosition.y = dPos.y;
|
|
}
|
|
|
|
};
|
|
|
|
// Global position of the primitive in the world image.
|
|
CPosition _Position;
|
|
|
|
// Time for valid getPos () position. _Position.getPos () == _3dInitPosition + _Speed * _InitTime;
|
|
double _InitTime;
|
|
|
|
// 3d position at t=0
|
|
NLMISC::CVectorD _3dInitPosition;
|
|
|
|
// Delta position is : _Speed*Deltatime
|
|
NLMISC::CVectorD _DeltaPosition;
|
|
|
|
// Current speed
|
|
NLMISC::CVectorD _Speed;
|
|
|
|
// Movable bounding box
|
|
double _BBXMin;
|
|
double _BBYMin;
|
|
double _BBXMax;
|
|
double _BBYMax;
|
|
|
|
// Union for data space shared by primitive type (cylinder or box)
|
|
union
|
|
{
|
|
// Data for Boxes
|
|
struct
|
|
{
|
|
// 2d position of the 4 points of the box at initial time.
|
|
double PointPosX[4];
|
|
double PointPosY[4];
|
|
|
|
// The normalized direction vector of the 4 edges of the box.
|
|
double EdgeDirectionX[4];
|
|
double EdgeDirectionY[4];
|
|
|
|
// The box orientation
|
|
double Orientation;
|
|
} _OBData;
|
|
};
|
|
|
|
// Sorted list of modified primitives. This pointer is managed by CMoveContainer.
|
|
CMovePrimitive *_NextModified;
|
|
|
|
// Pointer into the 4 possibles sorted lists of movable primitives. Can be NULL if not in the list
|
|
CMoveElement *_MoveElement[4];
|
|
};
|
|
|
|
|
|
} // NLPACS
|
|
|
|
|
|
#endif // NL_PRIMITIVE_WORLD_IMAGE_H
|
|
|
|
/* End of primitive_world_image.h */
|