Initial commit
This commit is contained in:
417
engines/hpl1/engine/physics/Body2D.cpp
Normal file
417
engines/hpl1/engine/physics/Body2D.cpp
Normal file
@@ -0,0 +1,417 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/Body2D.h"
|
||||
|
||||
#include "hpl1/engine/graphics/Mesh2d.h"
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
#include "hpl1/engine/physics/CollideData2D.h"
|
||||
#include "hpl1/engine/physics/Collider2D.h"
|
||||
#include "hpl1/engine/scene/Entity2D.h"
|
||||
#include "hpl1/engine/scene/Node2D.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cBody2D::cBody2D(const tString &asName, cMesh2D *apMesh, cVector2f avSize, cCollider2D *apCollider, int alID)
|
||||
: iEntity2D(asName) {
|
||||
mvSize = avSize;
|
||||
mpMesh = apMesh;
|
||||
mpCollider = apCollider;
|
||||
|
||||
mpCollMesh = mpMesh->CreateCollisonMesh(0, mvSize);
|
||||
mpBaseCollMesh = mpMesh->CreateCollisonMesh(0, mvSize);
|
||||
|
||||
/*for(int i=0;i<(int)mpCollMesh->mvPos.size();i++)
|
||||
{
|
||||
Log("Pos%d: %s\n", i,mpCollMesh->mvPos[i].ToString().c_str());
|
||||
}
|
||||
|
||||
for(int i=0;i<(int)mpCollMesh->mvNormal.size();i++)
|
||||
{
|
||||
Log("Norm%d: %s\n", i,mpCollMesh->mvNormal[i].ToString().c_str());
|
||||
}*/
|
||||
|
||||
// Log("------------\n");
|
||||
|
||||
// Set some default values to the properties
|
||||
mfMaxVel = 0;
|
||||
mfAcc = 1;
|
||||
|
||||
mfAirFriction = 0.005f;
|
||||
mfGroundFriction = 0.3f;
|
||||
mfGravity = 0.4f;
|
||||
mfMaxGravityVel = 3;
|
||||
|
||||
mbCollidable = false;
|
||||
mbCollides = true;
|
||||
mbMoved = false;
|
||||
mbOnGround = false;
|
||||
mbGroundFrictionX = false;
|
||||
mbGroundFrictionY = false;
|
||||
|
||||
mvCollideCount = 0;
|
||||
|
||||
mvMovement = 0;
|
||||
|
||||
mbAttachToGround = false;
|
||||
mbAttachBodies = true;
|
||||
|
||||
mpParentBody = NULL;
|
||||
|
||||
mpNode = NULL;
|
||||
mlID = alID;
|
||||
|
||||
mlCollideFlag = eFlagBit_0;
|
||||
mlCollideType = eFlagBit_1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cBody2D::~cBody2D() {
|
||||
hplDelete(mpCollMesh);
|
||||
hplDelete(mpBaseCollMesh);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::UpdateLogic(float afTimeStep) {
|
||||
cVector3f vStartPos = GetPosition();
|
||||
|
||||
if (mbAttachToGround) {
|
||||
if (mpParentBody != NULL) {
|
||||
// What can be done is to add this to the force, and then att the end redcue the same amout
|
||||
// This will allow the body to add the velocity to it's jumps for example.
|
||||
cVector3f vMovement = mpParentBody->GetMovement(); // mpParentBody->GetPosition() - mpParentBody->GetLastPosition();
|
||||
SetPosition(GetPosition() + vMovement);
|
||||
}
|
||||
}
|
||||
|
||||
cCollideData2D CollideData;
|
||||
// Update Gravity
|
||||
|
||||
mbGroundFrictionX = false;
|
||||
|
||||
if (mbCollides && mfGravity > 0) {
|
||||
cVector3f vTempPos = GetPosition();
|
||||
|
||||
float fXSize = mvSize.x;
|
||||
cRect2f Rect(vTempPos.x - fXSize / 2, vTempPos.y + mfGravity,
|
||||
fXSize, mvSize.y / 2);
|
||||
|
||||
if (mpCollider->CollideRect(Rect, GetCollideFlag(), NULL)) {
|
||||
// We are still on ground.
|
||||
mbOnGround = true;
|
||||
mbGroundFrictionX = true;
|
||||
// Log("Standing on ground\n");
|
||||
} else {
|
||||
// If the player used to be on ground, add some extra force
|
||||
if (mbOnGround) {
|
||||
mvForce.y += mfGravity * 2;
|
||||
}
|
||||
|
||||
mbOnGround = false;
|
||||
mvForce.y += mfGravity;
|
||||
if (mvForce.y > mfMaxGravityVel)
|
||||
mvForce.y = mfMaxGravityVel;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the Y Axis and check for collision
|
||||
AddPosXY(cVector2f(0, mvForce.y));
|
||||
|
||||
if (mbCollides) {
|
||||
UpdateCollisionMesh();
|
||||
UpdateBoundingBox();
|
||||
if (mpCollider->CollideBody(this, &CollideData)) {
|
||||
if (mvLastCollidePos.y == GetPosition().y)
|
||||
mvCollideCount.y++;
|
||||
|
||||
if (mvForce.y > 0) {
|
||||
if (mbAttachToGround) {
|
||||
// If collided with a body, make it the new reference frame.
|
||||
if (CollideData.mlstBodies.size() > 0) {
|
||||
tBody2DListIt it = CollideData.mlstBodies.begin();
|
||||
if (*it != mpParentBody) {
|
||||
if (mpParentBody != NULL)
|
||||
DetachBody(mpParentBody);
|
||||
|
||||
SetParentBody(*it);
|
||||
(*it)->AttachBody(this);
|
||||
// Log("Attaching!\n");
|
||||
}
|
||||
} else {
|
||||
if (mpParentBody != NULL) {
|
||||
DetachBody(mpParentBody);
|
||||
mpParentBody = NULL;
|
||||
// Log("Detaching!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbOnGround = true;
|
||||
mvForce.y = 0;
|
||||
}
|
||||
|
||||
if (mvCollideCount.y > 0) {
|
||||
|
||||
mvForce.y = 0;
|
||||
}
|
||||
|
||||
mvLastCollidePos.y = GetPosition().y;
|
||||
mbGroundFrictionX = true;
|
||||
} else {
|
||||
mvCollideCount.y = 0;
|
||||
if (!mbOnGround)
|
||||
mvLastCollidePos.y = -10000;
|
||||
// mbGroundFrictionX = false;
|
||||
}
|
||||
|
||||
if (mbOnGround == false && mbAttachToGround) {
|
||||
if (mpParentBody != NULL) {
|
||||
DetachBody(mpParentBody);
|
||||
mpParentBody = NULL;
|
||||
// Log("Detaching!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the X Axis and check for collision
|
||||
AddPosXY(cVector2f(mvForce.x, 0));
|
||||
|
||||
if (mbCollides) {
|
||||
UpdateCollisionMesh();
|
||||
UpdateBoundingBox();
|
||||
if (mpCollider->CollideBody(this, NULL)) {
|
||||
if (mvLastCollidePos.x == GetPosition().x)
|
||||
mvCollideCount.x++;
|
||||
|
||||
if (mvCollideCount.x > 0) {
|
||||
mvForce.x = 0;
|
||||
}
|
||||
|
||||
mvLastCollidePos.x = GetPosition().x;
|
||||
} else {
|
||||
mvCollideCount.x = 0;
|
||||
mvLastCollidePos.x = -10000;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the force
|
||||
float fAngle = 0, fStrength = 0;
|
||||
cMath::GetAngleFromVector(mvForce, &fAngle, &fStrength);
|
||||
|
||||
fStrength -= mfAirFriction; // This is the air friction.
|
||||
// It should be combined with the friction of the collided material.
|
||||
|
||||
if (fStrength < 0)
|
||||
fStrength = 0;
|
||||
|
||||
SetForce(fAngle, fStrength);
|
||||
|
||||
// Don't do any friction if the body has moved.
|
||||
// if(!mbMoved) Or?
|
||||
{
|
||||
if (mbGroundFrictionX && mvForce.x != 0) {
|
||||
// Log("GroundFriction!\n");
|
||||
// Log("Force: %s\n",mvForce.ToString().c_str());
|
||||
if (mvForce.x > 0) {
|
||||
mvForce.x -= mfGroundFriction;
|
||||
if (mvForce.x < 0)
|
||||
mvForce.x = 0;
|
||||
} else {
|
||||
mvForce.x += mfGroundFriction;
|
||||
if (mvForce.x > 0)
|
||||
mvForce.x = 0;
|
||||
}
|
||||
// Log("Force: %s\n",mvForce.ToString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
mvMovement = GetPosition() - vStartPos;
|
||||
|
||||
/*tBody2DListIt BodyIt = mlstAttachedBodies.begin();
|
||||
for(;BodyIt != mlstAttachedBodies.end();BodyIt++)
|
||||
{
|
||||
cBody2D* pBody = *BodyIt;
|
||||
|
||||
pBody->SetPosition(pBody->GetPosition() + vMovement);
|
||||
}*/
|
||||
|
||||
if (mpNode) {
|
||||
mpNode->SetPosition(GetWorldPosition());
|
||||
}
|
||||
|
||||
mbMoved = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::Move(float afValue) {
|
||||
float fAngle = 0, fStrength = 0;
|
||||
|
||||
cVector2f vForwardVec = cMath::GetVectorFromAngle2D(mvRotation.z, 1);
|
||||
cVector2f vMovement = cMath::ProjectVector2D(mvForce, vForwardVec);
|
||||
cMath::GetAngleFromVector(vMovement, &fAngle, &fStrength);
|
||||
|
||||
if (fStrength < mfMaxVel) {
|
||||
float fTempAcc = mfAcc;
|
||||
|
||||
if (fStrength + fTempAcc > mfMaxVel) {
|
||||
fTempAcc -= (fStrength + fTempAcc) - mfMaxVel;
|
||||
}
|
||||
|
||||
mvForce += vForwardVec * fTempAcc;
|
||||
|
||||
mbMoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::AddForce(float afAngle, float afStrength) {
|
||||
cVector2f vForce = cMath::GetVectorFromAngle2D(afAngle, afStrength);
|
||||
|
||||
AddForce(vForce);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::AddForce(const cVector2f &avForce) {
|
||||
mvForce += avForce;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::SetForce(float afAngle, float afStrength) {
|
||||
cVector2f vForce = cMath::GetVectorFromAngle2D(afAngle, afStrength);
|
||||
SetForce(vForce);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::SetForce(const cVector2f &avForce) {
|
||||
mvForce = avForce;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
const cRect2f &cBody2D::GetBoundingBox() {
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cBody2D::UpdateBoundingBox() {
|
||||
cVector2f vSize;
|
||||
|
||||
/*if(mvRotation.z != 0)
|
||||
{
|
||||
//Only Temp...
|
||||
float fMaxSize = sqrt(mvSize.x*mvSize.x + mvSize.y*mvSize.y);
|
||||
|
||||
vSize.x = fMaxSize;
|
||||
vSize.y = fMaxSize;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
vSize = mvSize;
|
||||
}
|
||||
|
||||
mBoundingBox = cRect2f(cVector2f(GetWorldPosition().x - vSize.x / 2,
|
||||
GetWorldPosition().y - vSize.y / 2),
|
||||
vSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::UpdateCollisionMesh() {
|
||||
cVector2f vPos(GetPosition().x, GetPosition().y);
|
||||
for (int i = 0; i < (int)mpCollMesh->mvPos.size(); i++) {
|
||||
mpCollMesh->mvPos[i] = vPos + mpBaseCollMesh->mvPos[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cCollisionMesh2D *cBody2D::GetCollisionMesh() {
|
||||
return mpCollMesh;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::AttachBody(cBody2D *apBody) {
|
||||
mlstAttachedBodies.push_back(apBody);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::DetachBody(cBody2D *apBody) {
|
||||
tBody2DListIt it = mlstAttachedBodies.begin();
|
||||
for (; it != mlstAttachedBodies.end(); it++) {
|
||||
if (*it == apBody) {
|
||||
mlstAttachedBodies.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::SetParentBody(cBody2D *apBody) {
|
||||
mpParentBody = apBody;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cBody2D::AddPosXY(cVector2f avPosAdd) {
|
||||
cVector3f vPos = GetPosition();
|
||||
vPos += avPosAdd;
|
||||
SetPosition(vPos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
186
engines/hpl1/engine/physics/Body2D.h
Normal file
186
engines/hpl1/engine/physics/Body2D.h
Normal file
@@ -0,0 +1,186 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_BODY_H
|
||||
#define HPL_BODY_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
|
||||
#include "common/list.h"
|
||||
#include "hpl1/engine/scene/Entity2D.h"
|
||||
#include "common/stablemap.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class cMesh2D;
|
||||
class cNode2D;
|
||||
class cCollider2D;
|
||||
class cCollisionMesh2D;
|
||||
|
||||
class cBody2D;
|
||||
|
||||
typedef Common::List<cBody2D *> tBody2DList;
|
||||
typedef tBody2DList::iterator tBody2DListIt;
|
||||
|
||||
class cBody2D : public iEntity2D {
|
||||
public:
|
||||
cBody2D(const tString &asName, cMesh2D *apMesh, cVector2f avSize, cCollider2D *apCollider, int alID);
|
||||
~cBody2D();
|
||||
|
||||
const cRect2f &GetBoundingBox();
|
||||
bool UpdateBoundingBox();
|
||||
|
||||
void Move(float afValue);
|
||||
|
||||
void UpdateLogic(float afTimeStep);
|
||||
|
||||
tString GetEntityType() { return "Body"; };
|
||||
|
||||
cVector3f &GetPosition() { return mvPosition; }
|
||||
cVector3f &GetLastPosition() { return mvLastPosition; }
|
||||
void ResetLastPosition() { mvLastPosition = mvPosition; }
|
||||
|
||||
float GetVelocity();
|
||||
float GetMaxVelocity() { return mfMaxVel; }
|
||||
float GetAcceleration() { return mfAcc; }
|
||||
float GetGravity() { return mfGravity; }
|
||||
float GetMaxGravityVel() { return mfMaxGravityVel; }
|
||||
bool GetCollidable() { return mbCollidable; }
|
||||
bool GetCollides() { return mbCollides; }
|
||||
float GetAirFriction() { return mfAirFriction; }
|
||||
float GetGroundFriction() { return mfGroundFriction; }
|
||||
const cVector2f &GetSize() { return mvSize; }
|
||||
|
||||
const cVector3f &GetMovement() { return mvMovement; }
|
||||
|
||||
void SetMaxVelocity(float afMaxVel) { mfMaxVel = afMaxVel; }
|
||||
void SetAcceleration(float afAcc) { mfAcc = afAcc; }
|
||||
void SetGravity(float afGravity) { mfGravity = afGravity; }
|
||||
void SetMaxGravityVel(float afMaxGravityVel) { mfMaxGravityVel = afMaxGravityVel; }
|
||||
void SetCollidable(bool abCollidable) { mbCollidable = abCollidable; }
|
||||
void SetCollides(bool abCollides) { mbCollides = abCollides; }
|
||||
void SetAirFriction(float afAirFriction) { mfAirFriction = afAirFriction; }
|
||||
void SetGroundFriction(float afGroundFriction) { mfGroundFriction = afGroundFriction; }
|
||||
|
||||
void AddForce(float afAngle, float afStrength);
|
||||
void AddForce(const cVector2f &avForce);
|
||||
|
||||
void SetForce(float afAngle, float afStrength);
|
||||
void SetForce(const cVector2f &avForce);
|
||||
|
||||
const cVector2f &GetForce() const { return mvForce; }
|
||||
|
||||
/**
|
||||
* Sets the things that the body can collide with, default is eFlagBit_0 (tiles)
|
||||
* \param alFlag
|
||||
*/
|
||||
void SetCollideFlag(tFlag alFlag) { mlCollideFlag = alFlag; }
|
||||
tFlag GetCollideFlag() { return mlCollideFlag; }
|
||||
|
||||
/**
|
||||
* Sets if the body is attached to moving obejcts and moves with the, default is false.
|
||||
* \param abX
|
||||
*/
|
||||
void SetAttachToGround(bool abX) { mbAttachToGround = abX; }
|
||||
bool GetAttachToGround() { return mbAttachToGround; }
|
||||
|
||||
/**
|
||||
* Sets if other objects can attach themselves to this body. Default is true.
|
||||
* \param abX
|
||||
*/
|
||||
void SetAttachBodies(bool abX) { mbAttachBodies = abX; }
|
||||
bool GetAttachBodies() { return mbAttachBodies; }
|
||||
|
||||
void AttachBody(cBody2D *apBody);
|
||||
void DetachBody(cBody2D *apBody);
|
||||
void SetParentBody(cBody2D *apBody);
|
||||
|
||||
/**
|
||||
* Sets the types of collider the body is, default is eFlagBit_1. On collision checking, the
|
||||
* other objects specify what it can collide with. And for every body this value is checked.
|
||||
* \param alFlag
|
||||
*/
|
||||
void SetCollideType(tFlag alFlag) { mlCollideType = alFlag; }
|
||||
tFlag GetCollideType() { return mlCollideType; }
|
||||
|
||||
void AttachNode(cNode2D *apNode) { mpNode = apNode; }
|
||||
void DetachNode() { mpNode = NULL; }
|
||||
|
||||
int GetID() { return mlID; }
|
||||
|
||||
bool OnGround() { return mbOnGround; }
|
||||
|
||||
void UpdateCollisionMesh();
|
||||
cCollisionMesh2D *GetCollisionMesh();
|
||||
|
||||
private:
|
||||
float mfMaxVel;
|
||||
float mfAcc;
|
||||
float mfGravity;
|
||||
float mfMaxGravityVel;
|
||||
float mfAirFriction;
|
||||
float mfGroundFriction;
|
||||
|
||||
bool mbCollides;
|
||||
bool mbCollidable;
|
||||
bool mbMoved;
|
||||
|
||||
cVector3f mvMovement;
|
||||
|
||||
bool mbAttachToGround;
|
||||
bool mbAttachBodies;
|
||||
tBody2DList mlstAttachedBodies;
|
||||
cBody2D *mpParentBody;
|
||||
|
||||
int mlID;
|
||||
|
||||
tFlag mlCollideFlag;
|
||||
tFlag mlCollideType;
|
||||
|
||||
cMesh2D *mpMesh;
|
||||
cCollider2D *mpCollider;
|
||||
cNode2D *mpNode;
|
||||
|
||||
cCollisionMesh2D *mpCollMesh;
|
||||
cCollisionMesh2D *mpBaseCollMesh;
|
||||
|
||||
bool mbOnGround;
|
||||
bool mbGroundFrictionX;
|
||||
bool mbGroundFrictionY;
|
||||
|
||||
cVector2f mvForce;
|
||||
cVector2f mvSize;
|
||||
|
||||
cVector2l mvCollideCount;
|
||||
cVector2f mvLastCollidePos;
|
||||
|
||||
void AddPosXY(cVector2f avPosAdd);
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_BODY_H
|
||||
1384
engines/hpl1/engine/physics/CharacterBody.cpp
Normal file
1384
engines/hpl1/engine/physics/CharacterBody.cpp
Normal file
File diff suppressed because it is too large
Load Diff
415
engines/hpl1/engine/physics/CharacterBody.h
Normal file
415
engines/hpl1/engine/physics/CharacterBody.h
Normal file
@@ -0,0 +1,415 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_CHARACTER_BODY_H
|
||||
#define HPL_CHARACTER_BODY_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iPhysicsWorld;
|
||||
class iCollideShape;
|
||||
class iPhysicsBody;
|
||||
class cCamera3D;
|
||||
class iCharacterBody;
|
||||
class iEntity3D;
|
||||
|
||||
enum eCharDir {
|
||||
eCharDir_Forward = 0,
|
||||
eCharDir_Right = 1,
|
||||
eCharDir_LastEnum = 2
|
||||
};
|
||||
|
||||
class iCharacterBodyCallback {
|
||||
public:
|
||||
virtual ~iCharacterBodyCallback() = default;
|
||||
virtual void OnHitGround(iCharacterBody *apCharBody, const cVector3f &avVel) = 0;
|
||||
virtual void OnGravityCollide(iCharacterBody *apCharBody, iPhysicsBody *apCollideBody,
|
||||
cCollideData *apCollideData) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class cCharacterBodyRay : public iPhysicsRayCallback {
|
||||
public:
|
||||
cCharacterBodyRay();
|
||||
|
||||
void Clear();
|
||||
bool OnIntersect(iPhysicsBody *pBody, cPhysicsRayParams *apParams);
|
||||
|
||||
float mfMinDist;
|
||||
bool mbCollide;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class cCharacterBodyCollideGravity : public iPhysicsWorldCollisionCallback {
|
||||
public:
|
||||
cCharacterBodyCollideGravity();
|
||||
|
||||
void OnCollision(iPhysicsBody *apBody, cCollideData *apCollideData);
|
||||
|
||||
iCharacterBody *mpCharBody;
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class cCharacterBodyCollidePush : public iPhysicsWorldCollisionCallback {
|
||||
public:
|
||||
cCharacterBodyCollidePush();
|
||||
|
||||
void OnCollision(iPhysicsBody *apBody, cCollideData *apCollideData);
|
||||
|
||||
iCharacterBody *mpCharBody;
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_BaseClass(iCharacterBody) {
|
||||
kSaveData_ClassInit(iCharacterBody) public : tString msName;
|
||||
|
||||
float mfMass;
|
||||
bool mbGravityActive;
|
||||
float mfMaxGravitySpeed;
|
||||
|
||||
bool mbActive;
|
||||
|
||||
bool mbCollideCharacter;
|
||||
|
||||
cVector3f mvPosition;
|
||||
cVector3f mvLastPosition;
|
||||
float mfMaxPosMoveSpeed[2];
|
||||
float mfMaxNegMoveSpeed[2];
|
||||
float mfMoveSpeed[2];
|
||||
float mfMoveAcc[2];
|
||||
float mfMoveDeacc[2];
|
||||
bool mbMoving[2];
|
||||
|
||||
float mfPitch;
|
||||
float mfYaw;
|
||||
|
||||
bool mbOnGround;
|
||||
|
||||
float mfMaxPushMass;
|
||||
float mfPushForce;
|
||||
bool mbPushIn2D;
|
||||
|
||||
cVector3f mvForce;
|
||||
cVector3f mvVelolcity;
|
||||
|
||||
cVector3f mvSize;
|
||||
|
||||
cMatrixf m_mtxMove;
|
||||
|
||||
int mlEntityId;
|
||||
cMatrixf m_mtxEntityOffset;
|
||||
int mlEntitySmoothPosNum;
|
||||
|
||||
float mfMaxStepHeight;
|
||||
float mfStepClimbSpeed;
|
||||
float mfClimbForwardMul;
|
||||
float mfClimbHeightAdd;
|
||||
bool mbClimbing;
|
||||
|
||||
float mfGroundFriction;
|
||||
float mfAirFriction;
|
||||
|
||||
int mlBodyId;
|
||||
|
||||
cContainerList<int> mvExtraBodyIds;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class iCharacterBody : public iSaveObject {
|
||||
typedef iSaveObject super;
|
||||
friend class cSaveData_iCharacterBody;
|
||||
friend class cCharacterBodyCollideGravity;
|
||||
|
||||
public:
|
||||
iCharacterBody(const tString &asName, iPhysicsWorld *apWorld, const cVector3f avSize);
|
||||
virtual ~iCharacterBody();
|
||||
|
||||
const tString &GetName() { return msName; }
|
||||
|
||||
///////////////////////////////////////
|
||||
// Properties
|
||||
|
||||
float GetMass();
|
||||
void SetMass(float afMass);
|
||||
|
||||
void SetActive(bool abX);
|
||||
bool IsActive() { return mbActive; }
|
||||
|
||||
cVector3f GetSize();
|
||||
|
||||
void SetCollideCharacter(bool abX);
|
||||
bool GetCollideCharacter() { return mbCollideCharacter; }
|
||||
|
||||
void SetTestCollision(bool abX) { mbTestCollision = abX; }
|
||||
bool GetTestCollision() { return mbTestCollision; }
|
||||
|
||||
void SetMaxPositiveMoveSpeed(eCharDir aDir, float afX);
|
||||
float GetMaxPositiveMoveSpeed(eCharDir aDir);
|
||||
void SetMaxNegativeMoveSpeed(eCharDir aDir, float afX);
|
||||
float GetMaxNegativeMoveSpeed(eCharDir aDir);
|
||||
|
||||
void SetMoveSpeed(eCharDir aDir, float afX);
|
||||
float GetMoveSpeed(eCharDir aDir);
|
||||
void SetMoveAcc(eCharDir aDir, float afX);
|
||||
float GetMoveAcc(eCharDir aDir);
|
||||
void SetMoveDeacc(eCharDir aDir, float afX);
|
||||
float GetMoveDeacc(eCharDir aDir);
|
||||
|
||||
cVector3f GetVelocity(float afFrameTime);
|
||||
|
||||
void SetPosition(const cVector3f &avPos, bool abSmooth = false);
|
||||
const cVector3f &GetPosition();
|
||||
const cVector3f &GetLastPosition();
|
||||
void SetFeetPosition(const cVector3f &avPos, bool abSmooth = false);
|
||||
cVector3f GetFeetPosition();
|
||||
|
||||
void SetYaw(float afX);
|
||||
void AddYaw(float afX);
|
||||
float GetYaw();
|
||||
void SetPitch(float afX);
|
||||
void AddPitch(float afX);
|
||||
float GetPitch();
|
||||
|
||||
cVector3f GetForward();
|
||||
cVector3f GetRight();
|
||||
cVector3f GetUp();
|
||||
|
||||
cMatrixf &GetMoveMatrix();
|
||||
|
||||
void SetGravityActive(bool abX);
|
||||
bool GravityIsActive();
|
||||
void SetMaxGravitySpeed(float afX);
|
||||
float GetMaxGravitySpeed();
|
||||
|
||||
bool GetCustomGravityActive();
|
||||
void SetCustomGravityActive(bool abX);
|
||||
void SetCustomGravity(const cVector3f &avCustomGravity);
|
||||
cVector3f GetCustomGravity();
|
||||
|
||||
void SetMaxPushMass(float afX) { mfMaxPushMass = afX; }
|
||||
void SetPushForce(float afX) { mfPushForce = afX; }
|
||||
float GetMaxPushMass() { return mfMaxPushMass; }
|
||||
float GetPushForce() { return mfPushForce; }
|
||||
|
||||
bool GetPushIn2D() { return mbPushIn2D; }
|
||||
void SetPushIn2D(bool abX) { mbPushIn2D = abX; }
|
||||
|
||||
void AddForceVelocity(const cVector3f &avVel) { mvVelolcity += avVel; }
|
||||
void SetForceVelocity(const cVector3f &avVel) { mvVelolcity = avVel; }
|
||||
cVector3f GetForceVelocity() { return mvVelolcity; }
|
||||
|
||||
int AddExtraSize(const cVector3f &avSize);
|
||||
void SetActiveSize(int alNum);
|
||||
|
||||
///////////////////////////////////////
|
||||
// Actions
|
||||
void SetForce(const cVector3f &avForce);
|
||||
void AddForce(const cVector3f &avForce);
|
||||
cVector3f GetForce();
|
||||
|
||||
void Move(eCharDir aDir, float afMul, float afTimeStep);
|
||||
|
||||
void Update(float afTimeStep);
|
||||
|
||||
///////////////////////////////////////
|
||||
// Other
|
||||
void SetCamera(cCamera3D *apCam);
|
||||
cCamera3D *GetCamera();
|
||||
void SetCameraPosAdd(const cVector3f &avAdd);
|
||||
cVector3f GetCameraPosAdd();
|
||||
void SetCameraSmoothPosNum(int alNum) { mlCameraSmoothPosNum = alNum; }
|
||||
int GetCameraSmoothPosNum() { return mlCameraSmoothPosNum; }
|
||||
|
||||
void SetEntity(iEntity3D *apEntity);
|
||||
iEntity3D *GetEntity();
|
||||
|
||||
void SetEntityOffset(const cMatrixf &a_mtxOffset);
|
||||
const cMatrixf &GetEntityOffset();
|
||||
|
||||
void SetEntityPostOffset(const cMatrixf &a_mtxOffset);
|
||||
const cMatrixf &GetEntityPostOffset();
|
||||
|
||||
void SetEntitySmoothPosNum(int alNum) { mlEntitySmoothPosNum = alNum; }
|
||||
int GetEntitySmoothPosNum() { return mlEntitySmoothPosNum; }
|
||||
|
||||
void SetUserData(void *apUserData) { mpUserData = apUserData; }
|
||||
void *GetUserData() { return mpUserData; }
|
||||
|
||||
void SetCallback(iCharacterBodyCallback *apCallback) { mpCallback = apCallback; }
|
||||
|
||||
void SetEnableNearbyBodies(bool abX) { mbEnableNearbyBodies = abX; }
|
||||
bool GetEnableNearbyBodies() { return mbEnableNearbyBodies; }
|
||||
|
||||
iPhysicsBody *GetBody() { return mpBody; }
|
||||
iCollideShape *GetShape();
|
||||
|
||||
iPhysicsBody *GetExtraBody(size_t alIdx) { return mvExtraBodies[alIdx]; }
|
||||
|
||||
bool IsOnGround();
|
||||
|
||||
float GetMaxStepSize() { return mfMaxStepHeight; }
|
||||
void SetMaxStepSize(float afSize) { mfMaxStepHeight = afSize; }
|
||||
|
||||
void SetStepClimbSpeed(float afX) { mfStepClimbSpeed = afX; }
|
||||
float GetStepClimbSpeed() { return mfStepClimbSpeed; }
|
||||
|
||||
void SetAccurateClimbing(bool abX) { mbAccurateClimbing = abX; }
|
||||
bool GetAccurateClimbing() { return mbAccurateClimbing; }
|
||||
|
||||
void SetClimbForwardMul(float afX) { mfClimbForwardMul = afX; }
|
||||
float GetClimbForwardMul() { return mfClimbForwardMul; }
|
||||
|
||||
void SetClimbHeightAdd(float afX) { mfClimbHeightAdd = afX; }
|
||||
float GetClimbHeightAdd() { return mfClimbHeightAdd; }
|
||||
|
||||
void SetGroundFriction(float afX) { mfGroundFriction = afX; }
|
||||
float GetGroundFriction() { return mfGroundFriction; }
|
||||
|
||||
void SetAirFriction(float afX) { mfAirFriction = afX; }
|
||||
float GetAirFriction() { return mfAirFriction; }
|
||||
|
||||
bool IsClimbing() { return mbClimbing; }
|
||||
|
||||
void SetAttachedBody(iPhysicsBody *apBody);
|
||||
iPhysicsBody *GetAttachedBody() { return mpAttachedBody; }
|
||||
|
||||
// O=nly sue when you know what you are doing, Update calls these
|
||||
void UpdateMoveMarix();
|
||||
|
||||
void UpdateCamera();
|
||||
void UpdateEntity();
|
||||
|
||||
void UpdateAttachment();
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
tString msName;
|
||||
|
||||
float mfMass;
|
||||
|
||||
bool mbActive;
|
||||
|
||||
bool mbCollideCharacter;
|
||||
|
||||
bool mbTestCollision;
|
||||
|
||||
bool mbGravityActive;
|
||||
float mfMaxGravitySpeed;
|
||||
bool mbCustomGravity;
|
||||
cVector3f mvCustomGravity;
|
||||
|
||||
cVector3f mvPosition;
|
||||
cVector3f mvLastPosition;
|
||||
|
||||
float mfMaxPosMoveSpeed[2];
|
||||
float mfMaxNegMoveSpeed[2];
|
||||
|
||||
float mfMoveSpeed[2];
|
||||
float mfMoveAcc[2];
|
||||
float mfMoveDeacc[2];
|
||||
bool mbMoving[2];
|
||||
|
||||
float mfPitch;
|
||||
float mfYaw;
|
||||
|
||||
bool mbOnGround;
|
||||
|
||||
float mfMaxPushMass;
|
||||
float mfPushForce;
|
||||
bool mbPushIn2D;
|
||||
|
||||
float mfCheckStepClimbCount;
|
||||
float mfCheckStepClimbInterval;
|
||||
|
||||
cVector3f mvForce;
|
||||
cVector3f mvVelolcity;
|
||||
|
||||
cVector3f mvSize;
|
||||
|
||||
cMatrixf m_mtxMove;
|
||||
|
||||
cCamera3D *mpCamera;
|
||||
cVector3f mvCameraPosAdd;
|
||||
int mlCameraSmoothPosNum;
|
||||
tVector3fList mlstCameraPos;
|
||||
|
||||
iEntity3D *mpEntity;
|
||||
cMatrixf m_mtxEntityOffset;
|
||||
cMatrixf m_mtxEntityPostOffset;
|
||||
int mlEntitySmoothPosNum;
|
||||
tVector3fList mlstEntityPos;
|
||||
|
||||
float mfGroundFriction;
|
||||
float mfAirFriction;
|
||||
|
||||
void *mpUserData;
|
||||
|
||||
iPhysicsBody *mpAttachedBody;
|
||||
cMatrixf m_mtxAttachedPrevMatrix;
|
||||
bool mbAttachmentJustAdded;
|
||||
|
||||
iCharacterBodyCallback *mpCallback;
|
||||
|
||||
cCharacterBodyRay *mpRayCallback;
|
||||
|
||||
cCharacterBodyCollideGravity *mpCollideCallbackGravity;
|
||||
cCharacterBodyCollidePush *mpCollideCallbackPush;
|
||||
|
||||
float mfMaxStepHeight;
|
||||
float mfStepClimbSpeed;
|
||||
float mfClimbForwardMul;
|
||||
float mfClimbHeightAdd;
|
||||
bool mbClimbing;
|
||||
bool mbAccurateClimbing;
|
||||
|
||||
bool mbEnableNearbyBodies;
|
||||
|
||||
iPhysicsBody *mpBody;
|
||||
iPhysicsWorld *mpWorld;
|
||||
|
||||
Common::Array<iPhysicsBody *> mvExtraBodies;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_CHARACTER_BODY_H
|
||||
58
engines/hpl1/engine/physics/CollideData.h
Normal file
58
engines/hpl1/engine/physics/CollideData.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_COLLIDE_DATA_H
|
||||
#define HPL_COLLIDE_DATA_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class cCollidePoint {
|
||||
public:
|
||||
cVector3f mvPoint;
|
||||
cVector3f mvNormal;
|
||||
float mfDepth;
|
||||
};
|
||||
|
||||
typedef Common::Array<cCollidePoint> tCollidePointVec;
|
||||
typedef tCollidePointVec::iterator tCollidePointVecIt;
|
||||
|
||||
class cCollideData {
|
||||
public:
|
||||
tCollidePointVec mvContactPoints;
|
||||
int mlNumOfPoints;
|
||||
|
||||
void SetMaxSize(int alSize) {
|
||||
mvContactPoints.resize(alSize);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_COLLIDE_DATA_H
|
||||
65
engines/hpl1/engine/physics/CollideData2D.h
Normal file
65
engines/hpl1/engine/physics/CollideData2D.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_COLLIDE_DATA_2D_H
|
||||
#define HPL_COLLIDE_DATA_2D_H
|
||||
|
||||
#include "common/list.h"
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/physics/Body2D.h"
|
||||
#include "hpl1/engine/scene/Tile.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class cCollidedTile {
|
||||
public:
|
||||
cCollidedTile(cTile *apTile, int alLayer) : mpTile(apTile), mlLayer(alLayer) {}
|
||||
cTile *mpTile;
|
||||
int mlLayer;
|
||||
};
|
||||
|
||||
typedef Common::List<cCollidedTile> tCollidedTileList;
|
||||
typedef tCollidedTileList::iterator tCollidedTileListIt;
|
||||
|
||||
class cCollideData2D {
|
||||
public:
|
||||
tCollidedTileList mlstTiles;
|
||||
tBody2DList mlstBodies;
|
||||
|
||||
cVector2f mvPushVec;
|
||||
|
||||
void Clear() {
|
||||
mlstBodies.clear();
|
||||
mlstTiles.clear();
|
||||
mvPushVec = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_COLLIDE_DATA_2D_H
|
||||
94
engines/hpl1/engine/physics/CollideShape.h
Normal file
94
engines/hpl1/engine/physics/CollideShape.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_COLLIDE_SHAPE_H
|
||||
#define HPL_COLLIDE_SHAPE_H
|
||||
|
||||
#include "hpl1/engine/math/BoundingVolume.h"
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
enum eCollideShapeType {
|
||||
eCollideShapeType_Null,
|
||||
eCollideShapeType_Box,
|
||||
eCollideShapeType_Sphere,
|
||||
eCollideShapeType_Cylinder,
|
||||
eCollideShapeType_Capsule,
|
||||
eCollideShapeType_ConvexHull,
|
||||
eCollideShapeType_Mesh,
|
||||
eCollideShapeType_Compound,
|
||||
eCollideShapeType_LastEnum
|
||||
};
|
||||
|
||||
class iPhysicsWorld;
|
||||
|
||||
class iCollideShape {
|
||||
public:
|
||||
iCollideShape(iPhysicsWorld *apWorld) : mlUserCount(0), mpWorld(apWorld) {}
|
||||
virtual ~iCollideShape() {}
|
||||
|
||||
virtual iCollideShape *GetSubShape(int alIdx) = 0;
|
||||
virtual int GetSubShapeNum() = 0;
|
||||
|
||||
cVector3f GetSize() { return mvSize; }
|
||||
|
||||
float GetRadius() { return mvSize.x; }
|
||||
float GetHeight() { return mvSize.y; }
|
||||
float GetWidth() { return mvSize.x; }
|
||||
float GetDepth() { return mvSize.z; }
|
||||
|
||||
const cMatrixf &GetOffset() { return m_mtxOffset; }
|
||||
|
||||
eCollideShapeType GetType() { return mType; }
|
||||
|
||||
void IncUserCount() { mlUserCount++; }
|
||||
void DecUserCount() { mlUserCount--; }
|
||||
|
||||
bool HasUsers() { return mlUserCount > 0; }
|
||||
int GetUserCount() { return mlUserCount; }
|
||||
|
||||
float GetVolume() { return mfVolume; }
|
||||
|
||||
cBoundingVolume &GetBoundingVolume() { return mBoundingVolume; }
|
||||
|
||||
protected:
|
||||
cVector3f mvSize;
|
||||
eCollideShapeType mType;
|
||||
cMatrixf m_mtxOffset;
|
||||
|
||||
int mlUserCount;
|
||||
|
||||
iPhysicsWorld *mpWorld;
|
||||
float mfVolume;
|
||||
|
||||
cBoundingVolume mBoundingVolume;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_COLLIDE_SHAPE_H
|
||||
447
engines/hpl1/engine/physics/Collider2D.cpp
Normal file
447
engines/hpl1/engine/physics/Collider2D.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/Collider2D.h"
|
||||
|
||||
#include "hpl1/engine/graphics/Mesh2d.h"
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
#include "hpl1/engine/physics/Body2D.h"
|
||||
#include "hpl1/engine/physics/CollideData2D.h"
|
||||
#include "hpl1/engine/scene/GridMap2D.h"
|
||||
#include "hpl1/engine/scene/TileMap.h"
|
||||
#include "hpl1/engine/scene/World2D.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cCollider2D::cCollider2D() {
|
||||
mpWorld = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cCollider2D::~cCollider2D() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
tFlag cCollider2D::CollideBody(cBody2D *apBody, cCollideData2D *apData) {
|
||||
tFlag lCollision = eFlagBit_None;
|
||||
|
||||
cRect2f CollideRect = apBody->GetBoundingBox();
|
||||
|
||||
cCollisionMesh2D *pCollMesh = apBody->GetCollisionMesh();
|
||||
|
||||
cVector2f vPushVector;
|
||||
cVector2f vLastPushVector;
|
||||
|
||||
/////// TEST COLLISION WITH TILES
|
||||
// float fTileSize = mpWorld->GetTileMap()->GetTileSize();
|
||||
// cRect2f TileRect = cRect2f(0, 0, fTileSize, fTileSize);
|
||||
|
||||
for (int i = 0; i < mpWorld->GetTileMap()->GetTileLayerNum(); i++) {
|
||||
if (mpWorld->GetTileMap()->GetTileLayer(i)->HasCollision() == false)
|
||||
continue;
|
||||
|
||||
iTileMapIt *pTileIt = mpWorld->GetTileMap()->GetRectIterator(CollideRect, i);
|
||||
|
||||
while (pTileIt->HasNext()) {
|
||||
cTile *pTile = pTileIt->Next();
|
||||
// TileRect.x = pTile->GetPosition().x - fTileSize / 2;
|
||||
// TileRect.y = pTile->GetPosition().y - fTileSize / 2;
|
||||
|
||||
// This can be used for material properties.
|
||||
// cTileDataNormal *pTData = static_cast<cTileDataNormal*>(pTile->GetTileData());
|
||||
|
||||
if (pTile->GetCollisionMesh() == NULL)
|
||||
continue;
|
||||
|
||||
if (Collide(pCollMesh, pTile->GetCollisionMesh(), vPushVector)) {
|
||||
if (apData)
|
||||
apData->mlstTiles.push_back(cCollidedTile(pTile, i));
|
||||
|
||||
cVector3f vD;
|
||||
vD = apBody->GetPosition() - pTile->GetPosition();
|
||||
if ((vD.x * vPushVector.x + vD.y * vPushVector.y) < 0.0f)
|
||||
vPushVector = vPushVector * -1;
|
||||
|
||||
cVector3f vPos = apBody->GetPosition();
|
||||
|
||||
bool bAlterX = true;
|
||||
bool bAlterY = true;
|
||||
|
||||
// reverse the latest push, maybe pos here instead?
|
||||
if (lCollision) {
|
||||
// If the current X push is grater use it instead.
|
||||
if (ABS(vPushVector.x) > ABS(vLastPushVector.x)) {
|
||||
vPos.x -= vLastPushVector.x;
|
||||
} else {
|
||||
bAlterX = false;
|
||||
}
|
||||
// If the current Y push is grater use it instead.
|
||||
if (ABS(vPushVector.y) > ABS(vLastPushVector.y)) {
|
||||
vPos.y -= vLastPushVector.y;
|
||||
bAlterY = true;
|
||||
} else {
|
||||
bAlterY = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bAlterX)
|
||||
vPos.x += vPushVector.x;
|
||||
if (bAlterY)
|
||||
vPos.y += vPushVector.y;
|
||||
|
||||
apBody->SetPosition(vPos);
|
||||
apBody->ResetLastPosition();
|
||||
|
||||
apBody->UpdateCollisionMesh();
|
||||
// not really needed until layer change
|
||||
CollideRect = apBody->GetBoundingBox();
|
||||
|
||||
lCollision |= eFlagBit_0;
|
||||
vLastPushVector = vPushVector;
|
||||
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
hplDelete(pTileIt);
|
||||
|
||||
// if(bCollision)break;
|
||||
}
|
||||
|
||||
/////// TEST COLLISION WITH BODIES
|
||||
iGridMap2DIt *pBodyIt = mpWorld->GetGridMapBodies()->GetRectIterator(CollideRect);
|
||||
|
||||
while (pBodyIt->HasNext()) {
|
||||
cBody2D *pBody = static_cast<cBody2D *>(pBodyIt->Next());
|
||||
|
||||
if (apBody == pBody)
|
||||
continue;
|
||||
|
||||
// eFlagBit_0 is probably just temporary.
|
||||
if (pBody->IsActive() && pBody->GetCollideType() & apBody->GetCollideFlag()) {
|
||||
pBody->UpdateCollisionMesh(); // Temp
|
||||
|
||||
if (Collide(pCollMesh, pBody->GetCollisionMesh(), vPushVector)) {
|
||||
if (apData)
|
||||
apData->mlstBodies.push_back(pBody);
|
||||
|
||||
cVector3f vD;
|
||||
vD = apBody->GetPosition() - pBody->GetPosition();
|
||||
if ((vD.x * vPushVector.x + vD.y * vPushVector.y) < 0.0f)
|
||||
vPushVector = vPushVector * -1;
|
||||
|
||||
cVector3f vPos = apBody->GetPosition();
|
||||
|
||||
vPos += vPushVector;
|
||||
apBody->SetPosition(vPos);
|
||||
apBody->ResetLastPosition();
|
||||
|
||||
// apBody->UpdateCollisionMesh();
|
||||
// not really needed until layer change
|
||||
CollideRect = apBody->GetBoundingBox();
|
||||
|
||||
lCollision |= eFlagBit_0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hplDelete(pBodyIt);
|
||||
|
||||
/// Do some stuff when colliding
|
||||
if (lCollision) {
|
||||
/*cVector3f vPos = apBody->GetPosition() + vPushVector;
|
||||
apBody->SetPosition(vPos);
|
||||
apBody->ResetLastPosition();*/
|
||||
|
||||
mDebug.mvPushVec = vPushVector;
|
||||
// mDebug.mvPushPos = cVector2f(apBody->GetPosition().x,apBody->GetPosition().y);
|
||||
}
|
||||
|
||||
return lCollision;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
tFlag cCollider2D::CollideRect(cRect2f &aRect, tFlag alCollideFlags, cCollideData2D *apData) {
|
||||
tFlag lCollision = eFlagBit_None;
|
||||
|
||||
cRect2f CollideRect = aRect;
|
||||
|
||||
cCollisionMesh2D *pCollMesh = hplNew(cCollisionMesh2D, ());
|
||||
pCollMesh->mvPos.resize(4);
|
||||
pCollMesh->mvNormal.resize(4);
|
||||
SetCollideMesh(pCollMesh, aRect);
|
||||
|
||||
cVector2f vPushVector;
|
||||
cVector2f vLastPushVector;
|
||||
|
||||
//// Check for all tiles if the flag is set
|
||||
if (alCollideFlags & eFlagBit_0) {
|
||||
// float fTileSize = mpWorld->GetTileMap()->GetTileSize();
|
||||
// cRect2f TileRect = cRect2f(0, 0, fTileSize, fTileSize);
|
||||
|
||||
for (int i = 0; i < mpWorld->GetTileMap()->GetTileLayerNum(); i++) {
|
||||
if (mpWorld->GetTileMap()->GetTileLayer(i)->HasCollision() == false)
|
||||
continue;
|
||||
|
||||
iTileMapIt *pTileIt = mpWorld->GetTileMap()->GetRectIterator(CollideRect, i);
|
||||
|
||||
while (pTileIt->HasNext()) {
|
||||
cTile *pTile = pTileIt->Next();
|
||||
// TileRect.x = pTile->GetPosition().x - fTileSize / 2;
|
||||
// TileRect.y = pTile->GetPosition().y - fTileSize / 2;
|
||||
|
||||
if (pTile->GetCollisionMesh() == NULL)
|
||||
continue;
|
||||
|
||||
if (apData)
|
||||
apData->mlstTiles.push_back(cCollidedTile(pTile, i));
|
||||
|
||||
if (Collide(pCollMesh, pTile->GetCollisionMesh(), vPushVector)) {
|
||||
cVector3f vD;
|
||||
vD = cVector3f(aRect.x, aRect.y, 0) - pTile->GetPosition();
|
||||
if ((vD.x * vPushVector.x + vD.y * vPushVector.y) < 0.0f)
|
||||
vPushVector = vPushVector * -1;
|
||||
|
||||
cVector3f vPos;
|
||||
vPos.x = aRect.x;
|
||||
vPos.y = aRect.y;
|
||||
|
||||
// reverse the latest push, maybe pos here instead?
|
||||
if (lCollision) {
|
||||
vPos -= vLastPushVector;
|
||||
}
|
||||
|
||||
vPos += vPushVector;
|
||||
aRect.x = vPos.x;
|
||||
aRect.y = vPos.y;
|
||||
|
||||
SetCollideMesh(pCollMesh, aRect);
|
||||
CollideRect = aRect;
|
||||
|
||||
lCollision |= eFlagBit_0;
|
||||
vLastPushVector = vPushVector;
|
||||
}
|
||||
}
|
||||
|
||||
hplDelete(pTileIt);
|
||||
}
|
||||
}
|
||||
|
||||
iGridMap2DIt *pBodyIt = mpWorld->GetGridMapBodies()->GetRectIterator(CollideRect);
|
||||
|
||||
while (pBodyIt->HasNext()) {
|
||||
cBody2D *pBody = static_cast<cBody2D *>(pBodyIt->Next());
|
||||
|
||||
if (pBody->IsActive() && pBody->GetCollideType() & alCollideFlags) {
|
||||
if (cMath::BoxCollision(CollideRect, pBody->GetBoundingBox())) {
|
||||
if (Collide(pCollMesh, pBody->GetCollisionMesh(), vPushVector)) {
|
||||
if (apData)
|
||||
apData->mlstBodies.push_back(pBody);
|
||||
|
||||
lCollision |= pBody->GetCollideType();
|
||||
|
||||
/*Perhaps fix the push vector here?*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hplDelete(pBodyIt);
|
||||
|
||||
/// Do some stuff when colliding
|
||||
if (lCollision) {
|
||||
if (apData)
|
||||
apData->mvPushVec = vPushVector;
|
||||
}
|
||||
|
||||
hplDelete(pCollMesh);
|
||||
|
||||
return lCollision;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
tFlag cCollider2D::CollideLine(const cVector2f &avStart, const cVector2f &avEnd, tFlag alCollideFlags,
|
||||
cCollideData2D *apData) {
|
||||
tFlag lCollision = eFlagBit_None;
|
||||
|
||||
//// Check for all tiles if the flag is set
|
||||
if (alCollideFlags & eFlagBit_0) {
|
||||
/*float fTileSize = */ mpWorld->GetTileMap()->GetTileSize();
|
||||
|
||||
for (int i = 0; i < mpWorld->GetTileMap()->GetTileLayerNum(); i++) {
|
||||
if (mpWorld->GetTileMap()->GetTileLayer(i)->HasCollision() == false)
|
||||
continue;
|
||||
|
||||
iTileMapIt *pTileIt = mpWorld->GetTileMap()->GetLineIterator(avStart, avEnd, i);
|
||||
|
||||
while (pTileIt->HasNext()) {
|
||||
cTile *pTile = pTileIt->Next();
|
||||
|
||||
if (pTile->GetCollisionMesh() == NULL)
|
||||
continue;
|
||||
// Log("Found tile!\n");
|
||||
|
||||
if (apData)
|
||||
apData->mlstTiles.push_back(cCollidedTile(pTile, i));
|
||||
|
||||
lCollision |= eFlagBit_0;
|
||||
}
|
||||
|
||||
hplDelete(pTileIt);
|
||||
}
|
||||
}
|
||||
|
||||
// hplDelete(pCollMesh);
|
||||
|
||||
return lCollision;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cCollider2D::SetCollideMesh(cCollisionMesh2D *apMesh, cRect2f &aRect) {
|
||||
apMesh->mvPos[0] = cVector2f(aRect.x, aRect.y);
|
||||
apMesh->mvPos[1] = cVector2f(aRect.x + aRect.w, aRect.y);
|
||||
apMesh->mvPos[2] = cVector2f(aRect.x + aRect.w, aRect.y + aRect.h);
|
||||
apMesh->mvPos[3] = cVector2f(aRect.x, aRect.y + aRect.w);
|
||||
|
||||
apMesh->mvNormal[0] = cVector2f(0, -1);
|
||||
apMesh->mvNormal[1] = cVector2f(1, 0);
|
||||
apMesh->mvNormal[2] = cVector2f(0, 1);
|
||||
apMesh->mvNormal[3] = cVector2f(-1, 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cVector2f FindMTD(cVector2f *pPushVector, int alNumVectors) {
|
||||
cVector2f MTD = pPushVector[0];
|
||||
float mind2 = pPushVector[0].x * pPushVector[0].x + pPushVector[0].y * pPushVector[0].y;
|
||||
for (int i = 1; i < alNumVectors; i++) {
|
||||
float fD2 = pPushVector[i].x * pPushVector[i].x + pPushVector[i].y * pPushVector[i].y;
|
||||
if (fD2 < mind2) {
|
||||
mind2 = fD2;
|
||||
MTD = pPushVector[i];
|
||||
}
|
||||
}
|
||||
return MTD;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cCollider2D::Collide(cCollisionMesh2D *apMeshA, cCollisionMesh2D *apMeshB, cVector2f &avMTD) {
|
||||
cVector2f vAxis[32];
|
||||
int lAxisNum = 0;
|
||||
|
||||
// Check separating planes for A
|
||||
for (int i = 0; i < (int)apMeshA->mvNormal.size(); i++) {
|
||||
vAxis[lAxisNum] = apMeshA->mvNormal[i];
|
||||
if (AxisSeparateMeshes(vAxis[lAxisNum], apMeshA, apMeshB)) {
|
||||
return false;
|
||||
}
|
||||
lAxisNum++;
|
||||
}
|
||||
|
||||
// Check separating planes for B
|
||||
for (int i = 0; i < (int)apMeshB->mvNormal.size(); i++) {
|
||||
vAxis[lAxisNum] = apMeshB->mvNormal[i];
|
||||
if (AxisSeparateMeshes(vAxis[lAxisNum], apMeshA, apMeshB)) {
|
||||
return false;
|
||||
}
|
||||
lAxisNum++;
|
||||
}
|
||||
|
||||
avMTD = FindMTD(vAxis, lAxisNum);
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cCollider2D::AxisSeparateMeshes(cVector2f &avAxis, cCollisionMesh2D *apMeshA,
|
||||
cCollisionMesh2D *apMeshB) {
|
||||
float fMinA, fMaxA;
|
||||
float fMinB, fMaxB;
|
||||
|
||||
CalculateInterval(avAxis, apMeshA, fMinA, fMaxA);
|
||||
CalculateInterval(avAxis, apMeshB, fMinB, fMaxB);
|
||||
|
||||
if (fMinA >= fMaxB || fMinB >= fMaxA)
|
||||
return true;
|
||||
|
||||
float fD0 = fMaxA - fMinB;
|
||||
float fD1 = fMaxB - fMinA;
|
||||
float fDepth = (fD0 < fD1) ? fD0 : fD1;
|
||||
|
||||
avAxis *= fDepth;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cCollider2D::CalculateInterval(const cVector2f &avAxis, cCollisionMesh2D *apMesh,
|
||||
float &afMin, float &afMax) {
|
||||
float fTemp = avAxis.x * apMesh->mvPos[0].x + avAxis.y * apMesh->mvPos[0].y;
|
||||
afMin = fTemp;
|
||||
afMax = fTemp;
|
||||
|
||||
for (int i = 1; i < (int)apMesh->mvPos.size(); i++) {
|
||||
fTemp = avAxis.x * apMesh->mvPos[i].x + avAxis.y * apMesh->mvPos[i].y;
|
||||
|
||||
if (fTemp < afMin) {
|
||||
afMin = fTemp;
|
||||
} else if (fTemp > afMax) {
|
||||
afMax = fTemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
89
engines/hpl1/engine/physics/Collider2D.h
Normal file
89
engines/hpl1/engine/physics/Collider2D.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_COLLIDER2D_H
|
||||
#define HPL_COLLIDER2D_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class cMesh2D;
|
||||
class cWorld2D;
|
||||
class cBody2D;
|
||||
class cCollideData2D;
|
||||
class cCollisionMesh2D;
|
||||
|
||||
class cCollider2DDebug {
|
||||
public:
|
||||
cVector2f mvPushVec;
|
||||
cVector2f mvPushPos;
|
||||
};
|
||||
|
||||
class cCollider2D {
|
||||
public:
|
||||
cCollider2D();
|
||||
~cCollider2D();
|
||||
|
||||
void SetWorld(cWorld2D *apWorld) { mpWorld = apWorld; }
|
||||
|
||||
/**
|
||||
* Collides a body with the world and returns a flag of what object has collided.
|
||||
* \param *apBody
|
||||
* \return 0= no collision, eFlagBit0 = Tiles, all other bits are custom.
|
||||
*/
|
||||
tFlag CollideBody(cBody2D *apBody, cCollideData2D *apData);
|
||||
|
||||
/**
|
||||
* Collides a custom rect with the world
|
||||
* \param aRect
|
||||
* \param alCollideFlags Specifies what things to check for collision with.
|
||||
* \return
|
||||
*/
|
||||
tFlag CollideRect(cRect2f &aRect, tFlag alCollideFlags, cCollideData2D *apData);
|
||||
|
||||
tFlag CollideLine(const cVector2f &avStart, const cVector2f &avEnd, tFlag alCollideFlags,
|
||||
cCollideData2D *apData);
|
||||
|
||||
cCollider2DDebug mDebug;
|
||||
|
||||
private:
|
||||
cWorld2D *mpWorld;
|
||||
|
||||
void SetCollideMesh(cCollisionMesh2D *apMesh, cRect2f &aRect);
|
||||
|
||||
bool Collide(cCollisionMesh2D *apMeshA, cCollisionMesh2D *apMeshB, cVector2f &avMTD);
|
||||
bool AxisSeparateMeshes(cVector2f &avAxis, cCollisionMesh2D *apMeshA,
|
||||
cCollisionMesh2D *apMeshB);
|
||||
void CalculateInterval(const cVector2f &avAxis, cCollisionMesh2D *apMesh,
|
||||
float &afMin, float &afMax);
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_COLLIDER2D_H
|
||||
47
engines/hpl1/engine/physics/LowLevelPhysics.h
Normal file
47
engines/hpl1/engine/physics/LowLevelPhysics.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_LOWLEVELPHYSICS_H
|
||||
#define HPL_LOWLEVELPHYSICS_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iPhysicsWorld;
|
||||
|
||||
class iLowLevelPhysics {
|
||||
public:
|
||||
virtual ~iLowLevelPhysics() {}
|
||||
|
||||
virtual iPhysicsWorld *CreateWorld() = 0;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_LOWLEVELPHYSICS_H
|
||||
292
engines/hpl1/engine/physics/Physics.cpp
Normal file
292
engines/hpl1/engine/physics/Physics.cpp
Normal file
@@ -0,0 +1,292 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/Physics.h"
|
||||
#include "hpl1/engine/physics/LowLevelPhysics.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
#include "hpl1/engine/physics/SurfaceData.h"
|
||||
#include "hpl1/engine/system/String.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
#include "hpl1/engine/impl/tinyXML/tinyxml.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cPhysics::cPhysics(iLowLevelPhysics *apLowLevelPhysics) : iUpdateable("HPL_Physics") {
|
||||
mpLowLevelPhysics = apLowLevelPhysics;
|
||||
|
||||
mpGameWorld = NULL;
|
||||
|
||||
mlMaxImpacts = 6;
|
||||
mfImpactDuration = 0.4f;
|
||||
|
||||
mbLog = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cPhysics::~cPhysics() {
|
||||
Log("Exiting Physics Module\n");
|
||||
Log("--------------------------------------------------------\n");
|
||||
|
||||
STLDeleteAll(mlstWorlds);
|
||||
STLMapDeleteAll(m_mapSurfaceData);
|
||||
|
||||
Log("--------------------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cPhysics::Init(cResources *apResources) {
|
||||
mpResources = apResources;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cPhysics::Update(float afTimeStep) {
|
||||
UpdateImpactCounts(afTimeStep);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsWorld *cPhysics::CreateWorld(bool abAddSurfaceData) {
|
||||
iPhysicsWorld *pWorld = mpLowLevelPhysics->CreateWorld();
|
||||
mlstWorlds.push_back(pWorld);
|
||||
|
||||
if (abAddSurfaceData) {
|
||||
tSurfaceDataMapIt it = m_mapSurfaceData.begin();
|
||||
for (; it != m_mapSurfaceData.end(); ++it) {
|
||||
cSurfaceData *apData = it->second;
|
||||
apData->ToMaterial(pWorld);
|
||||
}
|
||||
}
|
||||
|
||||
return pWorld;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cPhysics::DestroyWorld(iPhysicsWorld *apWorld) {
|
||||
STLFindAndDelete(mlstWorlds, apWorld);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cPhysics::CanPlayImpact() {
|
||||
if ((int)mlstImpactCounts.size() >= mlMaxImpacts)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPhysics::AddImpact() {
|
||||
mlstImpactCounts.push_back(cPhysicsImpactCount());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSurfaceData *cPhysics::CreateSurfaceData(const tString &asName) {
|
||||
cSurfaceData *pData = hplNew(cSurfaceData, (asName, this, mpResources));
|
||||
|
||||
m_mapSurfaceData.insert(tSurfaceDataMap::value_type(asName, pData));
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
cSurfaceData *cPhysics::GetSurfaceData(const tString &asName) {
|
||||
tSurfaceDataMapIt it = m_mapSurfaceData.find(asName);
|
||||
if (it == m_mapSurfaceData.end())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool cPhysics::LoadSurfaceData(const tString &asFile) {
|
||||
//////////////////////////////////
|
||||
// Open document
|
||||
TiXmlDocument *pXmlDoc = hplNew(TiXmlDocument, (asFile.c_str()));
|
||||
if (pXmlDoc->LoadFile() == false) {
|
||||
Error("Couldn't load XML file '%s'!\n", asFile.c_str());
|
||||
hplDelete(pXmlDoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Get the root.
|
||||
TiXmlElement *pRootElem = pXmlDoc->RootElement();
|
||||
|
||||
//////////////////////////
|
||||
// Iterate children
|
||||
TiXmlElement *pChildElem = pRootElem->FirstChildElement("Material");
|
||||
for (; pChildElem != NULL; pChildElem = pChildElem->NextSiblingElement("Material")) {
|
||||
tString sName = cString::ToString(pChildElem->Attribute("Name"), "");
|
||||
if (sName == "")
|
||||
continue;
|
||||
|
||||
cSurfaceData *pData = CreateSurfaceData(sName);
|
||||
|
||||
// Get properties
|
||||
pData->SetElasticity(cString::ToFloat(pChildElem->Attribute("Elasticity"), 0.5f));
|
||||
pData->SetKineticFriction(cString::ToFloat(pChildElem->Attribute("KineticFriction"), 0.3f));
|
||||
pData->SetStaticFriction(cString::ToFloat(pChildElem->Attribute("StaticFriction"), 0.3f));
|
||||
|
||||
pData->SetPriority(cString::ToInt(pChildElem->Attribute("Priority"), 0));
|
||||
|
||||
pData->SetElasticityCombMode(GetCombMode(pChildElem->Attribute("ElasticityMode")));
|
||||
pData->SetFrictionCombMode(GetCombMode(pChildElem->Attribute("FrictionMode")));
|
||||
|
||||
pData->GetStepType(cString::ToString(pChildElem->Attribute("StepType"), ""));
|
||||
|
||||
pData->SetMinScrapeSpeed(cString::ToFloat(pChildElem->Attribute("MinScrapeSpeed"), 0.7f));
|
||||
pData->SetMinScrapeFreq(cString::ToFloat(pChildElem->Attribute("MinScrapeFreq"), 0.7f));
|
||||
pData->SetMinScrapeFreqSpeed(cString::ToFloat(pChildElem->Attribute("MinScrapeFreqSpeed"), 0.7f));
|
||||
pData->SetMiddleScrapeSpeed(cString::ToFloat(pChildElem->Attribute("MiddleScrapeSpeed"), 1.2f));
|
||||
pData->SetMaxScrapeFreqSpeed(cString::ToFloat(pChildElem->Attribute("MaxScrapeFreqSpeed"), 3));
|
||||
pData->SetMaxScrapeFreq(cString::ToFloat(pChildElem->Attribute("MaxScrapeFreq"), 2));
|
||||
pData->SetMinScrapeContacts(cString::ToInt(pChildElem->Attribute("MinScrapeContacts"), 4));
|
||||
pData->SetScrapeSoundName(cString::ToString(pChildElem->Attribute("ScrapeSoundName"), ""));
|
||||
|
||||
pData->SetMinRollSpeed(cString::ToFloat(pChildElem->Attribute("MinRollSpeed"), 0.7f));
|
||||
pData->SetMinRollFreq(cString::ToFloat(pChildElem->Attribute("MinRollFreq"), 0.7f));
|
||||
pData->SetMinRollVolume(cString::ToFloat(pChildElem->Attribute("MinRollVolume"), 0.7f));
|
||||
pData->SetMinRollFreqSpeed(cString::ToFloat(pChildElem->Attribute("MinRollFreqSpeed"), 0.7f));
|
||||
pData->SetMiddleRollSpeed(cString::ToFloat(pChildElem->Attribute("MiddleRollSpeed"), 1.2f));
|
||||
pData->SetMaxRollFreqSpeed(cString::ToFloat(pChildElem->Attribute("MaxRollFreqSpeed"), 3));
|
||||
pData->SetMaxRollFreq(cString::ToFloat(pChildElem->Attribute("MaxRollFreq"), 2));
|
||||
pData->SetMaxRollVolume(cString::ToFloat(pChildElem->Attribute("MaxRollVolume"), 2));
|
||||
pData->SetRollSoundName(cString::ToString(pChildElem->Attribute("RollSoundName"), ""));
|
||||
|
||||
// Axes
|
||||
tString sAxisVec = cString::ToString(pChildElem->Attribute("RollAxis"), "");
|
||||
tStringVec vAxes;
|
||||
tFlag axisFlags = 0;
|
||||
cString::GetStringVec(sAxisVec, vAxes);
|
||||
for (size_t i = 0; i < vAxes.size(); ++i) {
|
||||
tString sAxis = cString::ToLowerCase(vAxes[i]);
|
||||
if (sAxis == "x")
|
||||
axisFlags |= eRollAxisFlag_X;
|
||||
else if (sAxis == "y")
|
||||
axisFlags |= eRollAxisFlag_Y;
|
||||
else if (sAxis == "z")
|
||||
axisFlags |= eRollAxisFlag_Z;
|
||||
}
|
||||
pData->SetRollAxisFlags(axisFlags);
|
||||
|
||||
/////////////////////////
|
||||
// Get Impact data
|
||||
TiXmlElement *pImpactElem = pChildElem->FirstChildElement("Impact");
|
||||
for (; pImpactElem != NULL; pImpactElem = pImpactElem->NextSiblingElement("Impact")) {
|
||||
float fMinSpeed = cString::ToFloat(pImpactElem->Attribute("MinSpeed"), 1);
|
||||
|
||||
cSurfaceImpactData *pImpactData = pData->CreateImpactData(fMinSpeed);
|
||||
|
||||
pImpactData->SetSoundName(cString::ToString(pImpactElem->Attribute("SoundName"), ""));
|
||||
pImpactData->SetPSName(cString::ToString(pImpactElem->Attribute("PSName"), ""));
|
||||
pImpactData->SetPSPrio(cString::ToInt(pImpactElem->Attribute("PSPrio"), 10));
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Get Hit data
|
||||
TiXmlElement *pHitElem = pChildElem->FirstChildElement("Hit");
|
||||
for (; pHitElem != NULL; pHitElem = pHitElem->NextSiblingElement("Hit")) {
|
||||
float fMinSpeed = cString::ToFloat(pHitElem->Attribute("MinSpeed"), 1);
|
||||
|
||||
cSurfaceImpactData *pHitData = pData->CreateHitData(fMinSpeed);
|
||||
|
||||
pHitData->SetSoundName(cString::ToString(pHitElem->Attribute("SoundName"), ""));
|
||||
pHitData->SetPSName(cString::ToString(pHitElem->Attribute("PSName"), ""));
|
||||
pHitData->SetPSPrio(cString::ToInt(pHitElem->Attribute("PSPrio"), 10));
|
||||
}
|
||||
|
||||
/*Log("Added %s e: %f sf: %f kf: %f emode: %d fmode: %d\n", pData->GetName().c_str(),
|
||||
pData->GetElasticity(), pData->GetStaticFriction(), pData->GetKineticFriction(),
|
||||
pData->GetElasticityCombMode(), pData->GetFrictionCombMode());*/
|
||||
}
|
||||
|
||||
hplDelete(pXmlDoc);
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ePhysicsMaterialCombMode cPhysics::GetCombMode(const char *apName) {
|
||||
if (apName == NULL)
|
||||
return ePhysicsMaterialCombMode_Average;
|
||||
|
||||
tString sMode = cString::ToLowerCase(apName);
|
||||
|
||||
if (sMode == "average")
|
||||
return ePhysicsMaterialCombMode_Average;
|
||||
if (sMode == "min")
|
||||
return ePhysicsMaterialCombMode_Min;
|
||||
if (sMode == "max")
|
||||
return ePhysicsMaterialCombMode_Max;
|
||||
if (sMode == "multiply")
|
||||
return ePhysicsMaterialCombMode_Multiply;
|
||||
|
||||
return ePhysicsMaterialCombMode_Average;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cPhysics::UpdateImpactCounts(float afTimeStep) {
|
||||
tPhysicsImpactCountListIt it = mlstImpactCounts.begin();
|
||||
while (it != mlstImpactCounts.end()) {
|
||||
it->mfCount += afTimeStep;
|
||||
if (it->mfCount > mfImpactDuration) {
|
||||
it = mlstImpactCounts.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
122
engines/hpl1/engine/physics/Physics.h
Normal file
122
engines/hpl1/engine/physics/Physics.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_Physics_H
|
||||
#define HPL_Physics_H
|
||||
|
||||
#include "common/list.h"
|
||||
#include "hpl1/engine/game/Updateable.h"
|
||||
#include "hpl1/engine/physics/PhysicsMaterial.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
#include "common/stablemap.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iLowLevelPhysics;
|
||||
class iPhysicsWorld;
|
||||
class cSurfaceData;
|
||||
class cWorld3D;
|
||||
class cResources;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
typedef Common::List<iPhysicsWorld *> tPhysicsWorldList;
|
||||
typedef tPhysicsWorldList::iterator tPhysicsWorldListIt;
|
||||
|
||||
typedef Common::StableMap<tString, cSurfaceData *> tSurfaceDataMap;
|
||||
typedef tSurfaceDataMap::iterator tSurfaceDataMapIt;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class cPhysicsImpactCount {
|
||||
public:
|
||||
cPhysicsImpactCount() { mfCount = 0; }
|
||||
|
||||
float mfCount;
|
||||
};
|
||||
|
||||
typedef Common::List<cPhysicsImpactCount> tPhysicsImpactCountList;
|
||||
typedef tPhysicsImpactCountList::iterator tPhysicsImpactCountListIt;
|
||||
|
||||
//------------------------------------------------
|
||||
|
||||
class cPhysics : public iUpdateable {
|
||||
public:
|
||||
cPhysics(iLowLevelPhysics *apLowLevelPhysics);
|
||||
~cPhysics();
|
||||
|
||||
void Init(cResources *apResources);
|
||||
|
||||
void Update(float afTimeStep);
|
||||
|
||||
iPhysicsWorld *CreateWorld(bool abAddSurfaceData);
|
||||
void DestroyWorld(iPhysicsWorld *apWorld);
|
||||
|
||||
cSurfaceData *CreateSurfaceData(const tString &asName);
|
||||
cSurfaceData *GetSurfaceData(const tString &asName);
|
||||
bool LoadSurfaceData(const tString &asFile);
|
||||
|
||||
iLowLevelPhysics *GetLowLevel() { return mpLowLevelPhysics; }
|
||||
|
||||
void SetGameWorld(cWorld3D *apWorld) { mpGameWorld = apWorld; }
|
||||
cWorld3D *GetGameWorld() { return mpGameWorld; }
|
||||
|
||||
void SetImpactDuration(float afX) { mfImpactDuration = afX; }
|
||||
float GetImpactDuration() { return mfImpactDuration; }
|
||||
|
||||
void SetMaxImpacts(int alX) { mlMaxImpacts = alX; }
|
||||
int GetMaxImpacts() { return mlMaxImpacts; }
|
||||
int GetNumOfImpacts() { return (int)mlstImpactCounts.size(); }
|
||||
|
||||
bool CanPlayImpact();
|
||||
void AddImpact();
|
||||
|
||||
void SetDebugLog(bool abX) { mbLog = abX; }
|
||||
bool GetDebugLog() { return mbLog; }
|
||||
|
||||
private:
|
||||
ePhysicsMaterialCombMode GetCombMode(const char *apName);
|
||||
|
||||
void UpdateImpactCounts(float afTimeStep);
|
||||
|
||||
iLowLevelPhysics *mpLowLevelPhysics;
|
||||
cResources *mpResources;
|
||||
|
||||
cWorld3D *mpGameWorld;
|
||||
|
||||
tPhysicsWorldList mlstWorlds;
|
||||
tSurfaceDataMap m_mapSurfaceData;
|
||||
|
||||
tPhysicsImpactCountList mlstImpactCounts;
|
||||
float mfImpactDuration;
|
||||
int mlMaxImpacts;
|
||||
bool mbLog;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_Physics_H
|
||||
564
engines/hpl1/engine/physics/PhysicsBody.cpp
Normal file
564
engines/hpl1/engine/physics/PhysicsBody.cpp
Normal file
@@ -0,0 +1,564 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
|
||||
#include "hpl1/engine/physics/CollideShape.h"
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
#include "hpl1/engine/physics/PhysicsMaterial.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
#include "hpl1/engine/physics/SurfaceData.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/scene/SoundEntity.h"
|
||||
#include "hpl1/engine/sound/SoundChannel.h"
|
||||
#include "hpl1/engine/sound/SoundHandler.h"
|
||||
|
||||
#include "hpl1/engine/scene/Node3D.h"
|
||||
|
||||
#include "common/algorithm.h"
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsBody::iPhysicsBody(const tString &asName, iPhysicsWorld *apWorld, iCollideShape *apShape)
|
||||
: iEntity3D(asName) {
|
||||
mpWorld = apWorld;
|
||||
mpShape = apShape;
|
||||
mpNode = NULL;
|
||||
|
||||
// Increment user count for the shape
|
||||
apShape->IncUserCount();
|
||||
|
||||
mBoundingVolume.SetLocalMinMax(apShape->GetBoundingVolume().GetMin(),
|
||||
apShape->GetBoundingVolume().GetMax());
|
||||
|
||||
// Set the default material so that body always has a material.
|
||||
mpMaterial = mpWorld->GetMaterialFromName("Default");
|
||||
|
||||
mpCharacterBody = NULL;
|
||||
|
||||
mbBlocksSound = false;
|
||||
mbBlocksLight = true;
|
||||
|
||||
mpScrapeBody = NULL;
|
||||
mpScrapeSoundEntity = NULL;
|
||||
mpRollSoundEntity = NULL;
|
||||
mbHasImpact = false;
|
||||
mbHasSlide = false;
|
||||
|
||||
mlSlideCount = 0;
|
||||
mlImpactCount = 0;
|
||||
|
||||
mlBuoyancyId = -1;
|
||||
|
||||
mbCanAttachCharacter = false;
|
||||
|
||||
mpUserData = NULL;
|
||||
|
||||
mbPushedByCharacterGravity = false;
|
||||
|
||||
mbIsCharacter = false;
|
||||
mbCollideCharacter = true;
|
||||
|
||||
mbIsRagDoll = false;
|
||||
mbCollideRagDoll = true;
|
||||
|
||||
mbCollide = true;
|
||||
|
||||
mbVolatile = false;
|
||||
|
||||
mbDisableAfterSimulation = false;
|
||||
|
||||
mbHasCollision = false;
|
||||
|
||||
m_mtxPrevScrapeMatrix = cMatrixf::Identity;
|
||||
|
||||
// Log("Creating body %s\n",msName.c_str());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsBody::~iPhysicsBody() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::Destroy() {
|
||||
// Log("Start Destroying newton body '%s' %d\n",msName.c_str(),(size_t)this);
|
||||
|
||||
if (mpNode)
|
||||
hplDelete(mpNode);
|
||||
mpWorld->DestroyShape(mpShape);
|
||||
|
||||
// Log(" Joints\n");
|
||||
for (int i = 0; i < (int)mvJoints.size(); i++) {
|
||||
iPhysicsJoint *pJoint = mvJoints[i];
|
||||
|
||||
pJoint->RemoveBody(this);
|
||||
|
||||
if (pJoint->GetParentBody() == NULL && pJoint->GetChildBody() == NULL) {
|
||||
mpWorld->DestroyJoint(pJoint);
|
||||
}
|
||||
|
||||
// Skip removing for now, just makes things messy...
|
||||
/*if( pJoint->GetParentBody() == this ||
|
||||
(pJoint->GetParentBody() == NULL && pJoint->GetChildBody()== this) )
|
||||
{
|
||||
//Log(" Destroy joint %d\n",(size_t)pJoint);
|
||||
mpWorld->DestroyJoint(pJoint);
|
||||
}
|
||||
else if(pJoint->GetParentBody() == this)
|
||||
{
|
||||
//Remove this body from the joint
|
||||
pJoint->RemoveBody(this);
|
||||
}*/
|
||||
}
|
||||
|
||||
// Log("Deleted body '%s'\n",msName.c_str());
|
||||
|
||||
if (mpScrapeSoundEntity && mpWorld->GetWorld3D()->SoundEntityExists(mpScrapeSoundEntity))
|
||||
mpWorld->GetWorld3D()->DestroySoundEntity(mpScrapeSoundEntity);
|
||||
if (mpRollSoundEntity && mpWorld->GetWorld3D()->SoundEntityExists(mpRollSoundEntity))
|
||||
mpWorld->GetWorld3D()->DestroySoundEntity(mpRollSoundEntity);
|
||||
|
||||
DeleteLowLevel();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cVector3f iPhysicsBody::GetVelocityAtPosition(cVector3f avPos) {
|
||||
return GetLinearVelocity() + cMath::Vector3Cross(GetAngularVelocity(), avPos - GetLocalPosition());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::AddJoint(iPhysicsJoint *apJoint) {
|
||||
mvJoints.push_back(apJoint);
|
||||
}
|
||||
|
||||
iPhysicsJoint *iPhysicsBody::GetJoint(int alIndex) {
|
||||
return mvJoints[alIndex];
|
||||
}
|
||||
|
||||
int iPhysicsBody::GetJointNum() {
|
||||
return (int)mvJoints.size();
|
||||
}
|
||||
|
||||
void iPhysicsBody::RemoveJoint(iPhysicsJoint *apJoint) {
|
||||
Common::Array<iPhysicsJoint *>::iterator it = mvJoints.begin();
|
||||
for (; it != mvJoints.end(); ++it) {
|
||||
if (*it == apJoint) {
|
||||
mvJoints.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::UpdateBeforeSimulate(float afTimeStep) {
|
||||
// if(msName == "headalive01_throat2") Log("headalive01_throat2 Active: %d\n", IsActive());
|
||||
// if(msName == "headalive01_throat") Log("headalive01_throat Active: %d\n", IsActive());
|
||||
|
||||
// Reset that the body has had contact
|
||||
SetHasSlide(false);
|
||||
SetHasImpact(false);
|
||||
mbHasCollision = false;
|
||||
}
|
||||
|
||||
void iPhysicsBody::UpdateAfterSimulate(float afTimeStep) {
|
||||
//////////////////////////////////
|
||||
// Check disabling from callback
|
||||
if (mbDisableAfterSimulation) {
|
||||
mbDisableAfterSimulation = false;
|
||||
SetEnabled(false);
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// Check slide sound
|
||||
if (HasSlide() == false) {
|
||||
if (GetScrapeSoundEntity()) {
|
||||
if (mlSlideCount <= 0) {
|
||||
// Log("Stopped scrape %d on body '%s' IN BODY!\n", (size_t)GetScrapeSoundEntity(),
|
||||
// GetName().c_str());
|
||||
|
||||
if (mpWorld->GetWorld3D())
|
||||
if (mpWorld->GetWorld3D()->SoundEntityExists(GetScrapeSoundEntity())) {
|
||||
GetScrapeSoundEntity()->FadeOut(5.2f);
|
||||
}
|
||||
|
||||
SetScrapeSoundEntity(NULL);
|
||||
SetScrapeBody(NULL);
|
||||
} else if (mlSlideCount > 0) {
|
||||
mlSlideCount--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mlSlideCount = 8;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// Update rolling sound
|
||||
if (mpMaterial)
|
||||
mpMaterial->GetSurfaceData()->UpdateRollEffect(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cNode3D *iPhysicsBody::GetNode() {
|
||||
return mpNode;
|
||||
}
|
||||
cNode3D *iPhysicsBody::CreateNode() {
|
||||
if (mpNode)
|
||||
return mpNode;
|
||||
|
||||
mpNode = hplNew(cNode3D, ());
|
||||
return mpNode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::AddBodyCallback(iPhysicsBodyCallback *apCallback) {
|
||||
mlstBodyCallbacks.push_back(apCallback);
|
||||
}
|
||||
|
||||
void iPhysicsBody::RemoveBodyCallback(iPhysicsBodyCallback *apCallback) {
|
||||
tPhysicsBodyCallbackListIt it = mlstBodyCallbacks.begin();
|
||||
for (; it != mlstBodyCallbacks.end(); ++it) {
|
||||
if (apCallback == *it) {
|
||||
mlstBodyCallbacks.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool iPhysicsBody::OnBeginCollision(iPhysicsBody *apBody) {
|
||||
if (mlstBodyCallbacks.empty())
|
||||
return true;
|
||||
|
||||
bool bReturn = true;
|
||||
|
||||
// Log("Checking before collide callbacks for '%s' ",apBody->GetName().c_str());
|
||||
|
||||
tPhysicsBodyCallbackListIt it = mlstBodyCallbacks.begin();
|
||||
for (; it != mlstBodyCallbacks.end(); ++it) {
|
||||
iPhysicsBodyCallback *pCallback = *it;
|
||||
|
||||
// Log("Callback %d ,",(size_t)pCallback);
|
||||
|
||||
if (pCallback->OnBeginCollision(this, apBody) == false)
|
||||
bReturn = false;
|
||||
}
|
||||
|
||||
// Log(" END\n");
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::OnCollide(iPhysicsBody *apBody, cPhysicsContactData *apContactData) {
|
||||
mbHasCollision = true;
|
||||
|
||||
if (mlstBodyCallbacks.empty())
|
||||
return;
|
||||
|
||||
// Log("Checking on collide callbacks for '%s' ",apBody->GetName().c_str());
|
||||
|
||||
tPhysicsBodyCallbackListIt it = mlstBodyCallbacks.begin();
|
||||
for (; it != mlstBodyCallbacks.end(); ++it) {
|
||||
iPhysicsBodyCallback *pCallback = *it;
|
||||
|
||||
// Log("Callback %d ,",(size_t)pCallback);
|
||||
|
||||
pCallback->OnCollide(this, apBody, apContactData);
|
||||
}
|
||||
|
||||
// Log(" END\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsMaterial *iPhysicsBody::GetMaterial() {
|
||||
return mpMaterial;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iCollideShape *iPhysicsBody::GetShape() {
|
||||
return mpShape;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::AddAttachedCharacter(iCharacterBody *apChar) {
|
||||
RemoveAttachedCharacter(apChar);
|
||||
|
||||
mlstAttachedCharacters.push_back(apChar);
|
||||
}
|
||||
|
||||
void iPhysicsBody::RemoveAttachedCharacter(iCharacterBody *apChar) {
|
||||
Common::List<iCharacterBody *>::iterator it = mlstAttachedCharacters.begin();
|
||||
for (; it != mlstAttachedCharacters.end(); ++it) {
|
||||
if (apChar == *it) {
|
||||
mlstAttachedCharacters.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerializeBase(cSaveData_iCollideShape)
|
||||
kSerializeVar(mType, eSerializeType_Int32)
|
||||
kSerializeVar(m_mtxOffset, eSerializeType_Matrixf)
|
||||
kSerializeVar(mvSize, eSerializeType_Vector3f)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerialize(cSaveData_iPhysicsBody, cSaveData_iEntity3D)
|
||||
kSerializeClassContainer(mlstShapes, cSaveData_iCollideShape, eSerializeType_Class)
|
||||
|
||||
kSerializeVar(msMaterial, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mbBlocksSound, eSerializeType_Bool)
|
||||
kSerializeVar(mbIsCharacter, eSerializeType_Bool)
|
||||
kSerializeVar(mbCollideCharacter, eSerializeType_Bool)
|
||||
|
||||
kSerializeVar(mvLinearVelocity, eSerializeType_Vector3f)
|
||||
kSerializeVar(mvAngularVelocity, eSerializeType_Vector3f)
|
||||
kSerializeVar(mfLinearDamping, eSerializeType_Float32)
|
||||
kSerializeVar(mfAngularDamping, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxLinearSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxAngularSpeed, eSerializeType_Float32)
|
||||
|
||||
kSerializeVar(mfMass, eSerializeType_Float32)
|
||||
|
||||
kSerializeVar(mbEnabled, eSerializeType_Bool)
|
||||
kSerializeVar(mbAutoDisable, eSerializeType_Bool)
|
||||
kSerializeVar(mbContinuousCollision, eSerializeType_Bool)
|
||||
|
||||
kSerializeVar(mbGravity, eSerializeType_Bool)
|
||||
|
||||
kSerializeVar(mbCollide, eSerializeType_Bool)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
static iCollideShape *_CreateShape(cSaveData_iCollideShape *apData, iPhysicsWorld *apWorld) {
|
||||
switch ((eCollideShapeType)apData->mType) {
|
||||
case eCollideShapeType_Box:
|
||||
return apWorld->CreateBoxShape(apData->mvSize, &apData->m_mtxOffset);
|
||||
case eCollideShapeType_Sphere:
|
||||
return apWorld->CreateSphereShape(apData->mvSize, &apData->m_mtxOffset);
|
||||
case eCollideShapeType_Cylinder:
|
||||
return apWorld->CreateCylinderShape(apData->mvSize.x, apData->mvSize.y, &apData->m_mtxOffset);
|
||||
case eCollideShapeType_Capsule:
|
||||
return apWorld->CreateCapsuleShape(apData->mvSize.x, apData->mvSize.y, &apData->m_mtxOffset);
|
||||
case eCollideShapeType_Null:
|
||||
case eCollideShapeType_ConvexHull:
|
||||
case eCollideShapeType_Mesh:
|
||||
case eCollideShapeType_Compound:
|
||||
case eCollideShapeType_LastEnum:
|
||||
break;
|
||||
}
|
||||
|
||||
Warning("Invalid shape type %d!\n", apData->mType);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static iCollideShape *CreateCollideShapeFromSave(cContainerList<cSaveData_iCollideShape> *apShapeList,
|
||||
iPhysicsWorld *apWorld) {
|
||||
cContainerListIterator<cSaveData_iCollideShape> it = apShapeList->GetIterator();
|
||||
if (apShapeList->Size() == 1) {
|
||||
return _CreateShape(&it.Next(), apWorld);
|
||||
} else {
|
||||
tCollideShapeVec vShapes;
|
||||
while (it.HasNext()) {
|
||||
vShapes.push_back(_CreateShape(&it.Next(), apWorld));
|
||||
}
|
||||
|
||||
return apWorld->CreateCompundShape(vShapes);
|
||||
}
|
||||
}
|
||||
|
||||
iSaveObject *cSaveData_iPhysicsBody::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
iPhysicsWorld *pWorld = apGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
|
||||
|
||||
// Get the collider
|
||||
iCollideShape *pShape = CreateCollideShapeFromSave(&mlstShapes, pWorld);
|
||||
if (pShape == NULL)
|
||||
return NULL;
|
||||
|
||||
iPhysicsBody *pBody = pWorld->CreateBody(msName, pShape);
|
||||
|
||||
return pBody;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int cSaveData_iPhysicsBody::GetSaveCreatePrio() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsBody::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsBody, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsBody);
|
||||
|
||||
// Collider
|
||||
CreateSaveCollideShapes(&pData->mlstShapes);
|
||||
|
||||
// Material
|
||||
pData->msMaterial = mpMaterial == NULL ? "" : mpMaterial->GetName();
|
||||
|
||||
// Save vars
|
||||
kSaveData_SaveTo(mbBlocksSound);
|
||||
kSaveData_SaveTo(mbIsCharacter);
|
||||
kSaveData_SaveTo(mbCollideCharacter);
|
||||
|
||||
// Save interface properties
|
||||
pData->mvLinearVelocity = GetLinearVelocity();
|
||||
pData->mvAngularVelocity = GetAngularVelocity();
|
||||
pData->mfLinearDamping = GetLinearDamping();
|
||||
pData->mfAngularDamping = GetAngularDamping();
|
||||
pData->mfMaxLinearSpeed = GetMaxLinearSpeed();
|
||||
pData->mfMaxAngularSpeed = GetMaxAngularSpeed();
|
||||
|
||||
pData->mfMass = GetMass();
|
||||
|
||||
pData->mbEnabled = GetEnabled();
|
||||
pData->mbAutoDisable = GetAutoDisable();
|
||||
pData->mbContinuousCollision = GetContinuousCollision();
|
||||
|
||||
pData->mbGravity = GetGravity();
|
||||
|
||||
pData->mbCollide = GetCollide();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsBody);
|
||||
|
||||
// Material
|
||||
if (pData->msMaterial != "") {
|
||||
iPhysicsMaterial *pMat = mpWorld->GetMaterialFromName(pData->msMaterial);
|
||||
if (pMat)
|
||||
SetMaterial(pMat);
|
||||
}
|
||||
|
||||
// Save vars
|
||||
kSaveData_LoadFrom(mbBlocksSound);
|
||||
kSaveData_LoadFrom(mbIsCharacter);
|
||||
kSaveData_LoadFrom(mbCollideCharacter);
|
||||
|
||||
// Save interface properties
|
||||
SetLinearVelocity(pData->mvLinearVelocity);
|
||||
SetAngularVelocity(pData->mvAngularVelocity);
|
||||
SetLinearDamping(pData->mfLinearDamping);
|
||||
SetAngularDamping(pData->mfAngularDamping);
|
||||
SetMaxLinearSpeed(pData->mfMaxLinearSpeed);
|
||||
SetMaxAngularSpeed(pData->mfMaxAngularSpeed);
|
||||
|
||||
SetMass(pData->mfMass);
|
||||
|
||||
SetEnabled(pData->mbEnabled);
|
||||
SetAutoDisable(pData->mbAutoDisable);
|
||||
SetContinuousCollision(pData->mbContinuousCollision);
|
||||
|
||||
SetGravity(pData->mbGravity);
|
||||
|
||||
SetCollide(pData->mbCollide);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsBody);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsBody::CreateSaveCollideShapes(cContainerList<cSaveData_iCollideShape> *apShapeList) {
|
||||
if (mpShape->GetType() == eCollideShapeType_Compound) {
|
||||
for (int i = 0; i < mpShape->GetSubShapeNum(); ++i) {
|
||||
iCollideShape *pShape = mpShape->GetSubShape(i);
|
||||
|
||||
cSaveData_iCollideShape Shape;
|
||||
Shape.mType = (int)pShape->GetType();
|
||||
Shape.m_mtxOffset = pShape->GetOffset();
|
||||
Shape.mvSize = pShape->GetSize();
|
||||
|
||||
apShapeList->Add(Shape);
|
||||
}
|
||||
} else {
|
||||
cSaveData_iCollideShape Shape;
|
||||
Shape.mType = (int)mpShape->GetType();
|
||||
Shape.m_mtxOffset = mpShape->GetOffset();
|
||||
Shape.mvSize = mpShape->GetSize();
|
||||
|
||||
apShapeList->Add(Shape);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
332
engines/hpl1/engine/physics/PhysicsBody.h
Normal file
332
engines/hpl1/engine/physics/PhysicsBody.h
Normal file
@@ -0,0 +1,332 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_BODY_H
|
||||
#define HPL_PHYSICS_BODY_H
|
||||
|
||||
#include "hpl1/engine/graphics/GraphicsTypes.h"
|
||||
#include "hpl1/engine/scene/Entity3D.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iPhysicsWorld;
|
||||
class iCollideShape;
|
||||
class iPhysicsMaterial;
|
||||
class iLowLevelGraphics;
|
||||
class cNode3D;
|
||||
class cSoundEntity;
|
||||
class iPhysicsJoint;
|
||||
class cPhysicsContactData;
|
||||
class iCharacterBody;
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
class iPhysicsBody;
|
||||
class iPhysicsBodyCallback {
|
||||
public:
|
||||
virtual ~iPhysicsBodyCallback() {}
|
||||
virtual bool OnBeginCollision(iPhysicsBody *apBody, iPhysicsBody *apCollideBody) = 0;
|
||||
virtual void OnCollide(iPhysicsBody *apBody, iPhysicsBody *apCollideBody,
|
||||
cPhysicsContactData *apContactData) = 0;
|
||||
};
|
||||
|
||||
typedef Common::List<iPhysicsBodyCallback *> tPhysicsBodyCallbackList;
|
||||
typedef tPhysicsBodyCallbackList::iterator tPhysicsBodyCallbackListIt;
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
class cSaveData_iCollideShape : public iSerializable {
|
||||
kSerializableClassInit(cSaveData_iCollideShape) public : int mType;
|
||||
cMatrixf m_mtxOffset;
|
||||
cVector3f mvSize;
|
||||
};
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
kSaveData_ChildClass(iEntity3D, iPhysicsBody) {
|
||||
kSaveData_ClassInit(iPhysicsBody) public : cContainerList<cSaveData_iCollideShape> mlstShapes;
|
||||
|
||||
tString msMaterial;
|
||||
|
||||
bool mbBlocksSound;
|
||||
bool mbIsCharacter;
|
||||
bool mbCollideCharacter;
|
||||
|
||||
cVector3f mvLinearVelocity;
|
||||
cVector3f mvAngularVelocity;
|
||||
float mfLinearDamping;
|
||||
float mfAngularDamping;
|
||||
float mfMaxLinearSpeed;
|
||||
float mfMaxAngularSpeed;
|
||||
|
||||
float mfMass;
|
||||
|
||||
bool mbEnabled;
|
||||
bool mbAutoDisable;
|
||||
bool mbContinuousCollision;
|
||||
|
||||
bool mbGravity;
|
||||
|
||||
bool mbCollide;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
struct cPhysicsBody_Buoyancy {
|
||||
cPhysicsBody_Buoyancy() : mbActive(false), mfDensity(1),
|
||||
mfLinearViscosity(1), mfAngularViscosity(1) {}
|
||||
|
||||
bool mbActive;
|
||||
|
||||
float mfDensity;
|
||||
float mfLinearViscosity;
|
||||
float mfAngularViscosity;
|
||||
|
||||
cPlanef mSurface;
|
||||
};
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
class iPhysicsBody : public iEntity3D {
|
||||
typedef iEntity3D super;
|
||||
|
||||
public:
|
||||
iPhysicsBody(const tString &asName, iPhysicsWorld *apWorld, iCollideShape *apShape);
|
||||
virtual ~iPhysicsBody();
|
||||
|
||||
void Destroy();
|
||||
|
||||
virtual void SetMaterial(iPhysicsMaterial *apMaterial) = 0;
|
||||
iPhysicsMaterial *GetMaterial();
|
||||
|
||||
cNode3D *GetNode();
|
||||
cNode3D *CreateNode();
|
||||
|
||||
iCollideShape *GetShape();
|
||||
|
||||
void AddJoint(iPhysicsJoint *apJoint);
|
||||
iPhysicsJoint *GetJoint(int alIndex);
|
||||
int GetJointNum();
|
||||
void RemoveJoint(iPhysicsJoint *apJoint);
|
||||
|
||||
virtual void SetLinearVelocity(const cVector3f &avVel) = 0;
|
||||
virtual cVector3f GetLinearVelocity() const = 0;
|
||||
virtual void SetAngularVelocity(const cVector3f &avVel) = 0;
|
||||
virtual cVector3f GetAngularVelocity() const = 0;
|
||||
virtual void SetLinearDamping(float afDamping) = 0;
|
||||
virtual float GetLinearDamping() const = 0;
|
||||
virtual void SetAngularDamping(float afDamping) = 0;
|
||||
virtual float GetAngularDamping() const = 0;
|
||||
virtual void SetMaxLinearSpeed(float afSpeed) = 0;
|
||||
virtual float GetMaxLinearSpeed() const = 0;
|
||||
virtual void SetMaxAngularSpeed(float afDamping) = 0;
|
||||
virtual float GetMaxAngularSpeed() const = 0;
|
||||
virtual cMatrixf GetInertiaMatrix() = 0;
|
||||
|
||||
cVector3f GetVelocityAtPosition(cVector3f avPos);
|
||||
|
||||
virtual void SetMass(float afMass) = 0;
|
||||
virtual float GetMass() const = 0;
|
||||
virtual void SetMassCentre(const cVector3f &avCentre) = 0;
|
||||
virtual cVector3f GetMassCentre() const = 0;
|
||||
|
||||
virtual void AddForce(const cVector3f &avForce) = 0;
|
||||
virtual void AddForceAtPosition(const cVector3f &avForce, const cVector3f &avPos) = 0;
|
||||
virtual void AddTorque(const cVector3f &avTorque) = 0;
|
||||
virtual void AddImpulse(const cVector3f &avImpulse) = 0;
|
||||
virtual void AddImpulseAtPosition(const cVector3f &avImpulse, const cVector3f &avPos) = 0;
|
||||
|
||||
virtual void SetEnabled(bool abEnabled) = 0;
|
||||
virtual bool GetEnabled() const = 0;
|
||||
virtual void SetAutoDisable(bool abEnabled) = 0;
|
||||
virtual bool GetAutoDisable() const = 0;
|
||||
#if 0
|
||||
virtual void SetAutoDisableLinearThreshold(float afThresold) = 0;
|
||||
virtual float GetAutoDisableLinearThreshold() const = 0;
|
||||
virtual void SetAutoDisableAngularThreshold(float afThresold) = 0;
|
||||
virtual float GetAutoDisableAngularThreshold() const = 0;
|
||||
virtual void SetAutoDisableNumSteps(int alNum) = 0;
|
||||
virtual int GetAutoDisableNumSteps() const = 0;
|
||||
#endif
|
||||
virtual void SetContinuousCollision(bool abOn) = 0;
|
||||
virtual bool GetContinuousCollision() = 0;
|
||||
|
||||
virtual void SetGravity(bool abEnabled) = 0;
|
||||
virtual bool GetGravity() const = 0;
|
||||
|
||||
virtual void RenderDebugGeometry(iLowLevelGraphics *apLowLevel, const cColor &aColor) = 0;
|
||||
|
||||
void UpdateBeforeSimulate(float afTimeStep);
|
||||
void UpdateAfterSimulate(float afTimeStep);
|
||||
|
||||
cBoundingVolume *GetBV() { return &mBoundingVolume; }
|
||||
|
||||
void SetBlocksSound(bool abX) { mbBlocksSound = abX; }
|
||||
bool GetBlocksSound() { return mbBlocksSound; }
|
||||
|
||||
void SetBlocksLight(bool abX) { mbBlocksLight = abX; }
|
||||
bool GetBlocksLight() { return mbBlocksLight; }
|
||||
|
||||
void SetScrapeSoundEntity(cSoundEntity *apEntity) { mpScrapeSoundEntity = apEntity; }
|
||||
cSoundEntity *GetScrapeSoundEntity() { return mpScrapeSoundEntity; }
|
||||
void SetScrapeBody(iPhysicsBody *apBody) { mpScrapeBody = apBody; }
|
||||
iPhysicsBody *GetScrapeBody() { return mpScrapeBody; }
|
||||
const cMatrixf &GetPreveScrapeMatrix() { return m_mtxPrevScrapeMatrix; }
|
||||
void SetPreveScrapeMatrix(const cMatrixf &a_mtxMtx) { m_mtxPrevScrapeMatrix = a_mtxMtx; }
|
||||
|
||||
void SetRollSoundEntity(cSoundEntity *apEntity) { mpRollSoundEntity = apEntity; }
|
||||
cSoundEntity *GetRollSoundEntity() { return mpRollSoundEntity; }
|
||||
|
||||
void SetHasImpact(bool abX) { mbHasImpact = abX; }
|
||||
bool HasImpact() { return mbHasImpact; }
|
||||
void SetHasSlide(bool abX) { mbHasSlide = abX; }
|
||||
bool HasSlide() { return mbHasSlide; }
|
||||
|
||||
bool HasCollision() { return mbHasCollision; }
|
||||
|
||||
void SetUserData(void *apUserData) { mpUserData = apUserData; }
|
||||
void *GetUserData() { return mpUserData; }
|
||||
|
||||
void AddBodyCallback(iPhysicsBodyCallback *apCallback);
|
||||
void RemoveBodyCallback(iPhysicsBodyCallback *apCallback);
|
||||
|
||||
bool OnBeginCollision(iPhysicsBody *apBody);
|
||||
void OnCollide(iPhysicsBody *apBody, cPhysicsContactData *apContactData);
|
||||
|
||||
void SetCollide(bool abX) { mbCollide = abX; }
|
||||
bool GetCollide() { return mbCollide; }
|
||||
|
||||
void SetIsCharacter(bool abX) { mbIsCharacter = abX; }
|
||||
bool IsCharacter() { return mbIsCharacter; }
|
||||
|
||||
void SetCollideCharacter(bool abX) { mbCollideCharacter = abX; }
|
||||
bool GetCollideCharacter() { return mbCollideCharacter; }
|
||||
|
||||
void SetCharacterBody(iCharacterBody *apCharBody) { mpCharacterBody = apCharBody; }
|
||||
iCharacterBody *GetCharacterBody() { return mpCharacterBody; }
|
||||
|
||||
void SetIsRagDoll(bool abX) { mbIsRagDoll = abX; }
|
||||
bool IsRagDoll() { return mbIsRagDoll; }
|
||||
|
||||
void SetCollideRagDoll(bool abX) { mbCollideRagDoll = abX; }
|
||||
bool GetCollideRagDoll() { return mbCollideRagDoll; }
|
||||
|
||||
void SetVolatile(bool abX) { mbVolatile = abX; }
|
||||
bool IsVolatile() { return mbVolatile; }
|
||||
|
||||
void SetPushedByCharacterGravity(bool abX) { mbPushedByCharacterGravity = abX; }
|
||||
bool GetPushedByCharacterGravity() { return mbPushedByCharacterGravity; }
|
||||
|
||||
void SetBuoyancyId(int alX) { mlBuoyancyId = alX; }
|
||||
void SetBuoyancyActive(bool abX) { mBuoyancy.mbActive = abX; }
|
||||
void SetBuoyancyDensity(float afX) { mBuoyancy.mfDensity = afX; }
|
||||
void SetBuoyancyLinearViscosity(float afX) { mBuoyancy.mfLinearViscosity = afX; }
|
||||
void SetBuoyancyAngularViscosity(float afX) { mBuoyancy.mfAngularViscosity = afX; }
|
||||
void SetBuoyancySurface(const cPlanef &aP) { mBuoyancy.mSurface = aP; }
|
||||
|
||||
int GetBuoyancyId() { return mlBuoyancyId; }
|
||||
bool GetBuoyancyActive() { return mBuoyancy.mbActive; }
|
||||
float GetBuoyancyDensity() { return mBuoyancy.mfDensity; }
|
||||
float GetBuoyancyLinearViscosity() { return mBuoyancy.mfLinearViscosity; }
|
||||
float GetBuoyancyAngularViscosity() { return mBuoyancy.mfAngularViscosity; }
|
||||
cPlanef SetBuoyancySurface() { return mBuoyancy.mSurface; }
|
||||
|
||||
void SetCanAttachCharacter(bool abX) { mbCanAttachCharacter = abX; }
|
||||
bool GetCanAttachCharacter() { return mbCanAttachCharacter; }
|
||||
void AddAttachedCharacter(iCharacterBody *apChar);
|
||||
void RemoveAttachedCharacter(iCharacterBody *apChar);
|
||||
|
||||
iPhysicsWorld *GetWorld() { return mpWorld; }
|
||||
|
||||
void DisableAfterSimulation() { mbDisableAfterSimulation = true; }
|
||||
|
||||
// Entity implementation
|
||||
tString GetEntityType() { return "Body"; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
virtual void DeleteLowLevel() = 0;
|
||||
|
||||
protected:
|
||||
void CreateSaveCollideShapes(cContainerList<cSaveData_iCollideShape> *apShapeList);
|
||||
|
||||
iPhysicsWorld *mpWorld;
|
||||
iCollideShape *mpShape;
|
||||
iPhysicsMaterial *mpMaterial;
|
||||
cNode3D *mpNode;
|
||||
|
||||
iCharacterBody *mpCharacterBody;
|
||||
|
||||
Common::Array<iPhysicsJoint *> mvJoints;
|
||||
|
||||
Common::List<iCharacterBody *> mlstAttachedCharacters;
|
||||
|
||||
iPhysicsBody *mpScrapeBody;
|
||||
cSoundEntity *mpScrapeSoundEntity;
|
||||
cSoundEntity *mpRollSoundEntity;
|
||||
cMatrixf m_mtxPrevScrapeMatrix;
|
||||
bool mbHasImpact;
|
||||
bool mbHasSlide;
|
||||
int mlSlideCount;
|
||||
int mlImpactCount;
|
||||
|
||||
bool mbPushedByCharacterGravity;
|
||||
|
||||
bool mbBlocksSound;
|
||||
bool mbBlocksLight;
|
||||
bool mbIsCharacter;
|
||||
bool mbCollideCharacter;
|
||||
bool mbIsRagDoll;
|
||||
bool mbCollideRagDoll;
|
||||
bool mbVolatile;
|
||||
|
||||
bool mbCanAttachCharacter;
|
||||
|
||||
cPhysicsBody_Buoyancy mBuoyancy;
|
||||
int mlBuoyancyId;
|
||||
|
||||
bool mbDisableAfterSimulation;
|
||||
|
||||
bool mbHasCollision;
|
||||
|
||||
tPhysicsBodyCallbackList mlstBodyCallbacks;
|
||||
|
||||
void *mpUserData;
|
||||
|
||||
bool mbCollide;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_BODY_H
|
||||
349
engines/hpl1/engine/physics/PhysicsController.cpp
Normal file
349
engines/hpl1/engine/physics/PhysicsController.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsController.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
bool iPhysicsController::mbUseInputMatrixFix = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsController::iPhysicsController(const tString &asName, iPhysicsWorld *apWorld) {
|
||||
msName = asName;
|
||||
|
||||
mpWorld = apWorld;
|
||||
|
||||
mpBody = NULL;
|
||||
mpJoint = NULL;
|
||||
|
||||
mbActive = false;
|
||||
|
||||
mPidController.SetErrorNum(10);
|
||||
|
||||
mbMulMassWithOutput = false;
|
||||
|
||||
mfMaxOutput = 0;
|
||||
|
||||
mbLogInfo = false;
|
||||
|
||||
mbPaused = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsController::~iPhysicsController() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::SetPidIntegralSize(int alSize) {
|
||||
mPidController.SetErrorNum(alSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::Update(float afTimeStep) {
|
||||
if (mbActive == false || mbPaused)
|
||||
return;
|
||||
if (mpBody == NULL)
|
||||
return;
|
||||
|
||||
cVector3f vInput = GetInputValue(mInputType);
|
||||
// Get the local input.
|
||||
if (mbUseInputMatrixFix == false ||
|
||||
(mInputType != ePhysicsControllerInput_JointAngle && mInputType != ePhysicsControllerInput_JointDist)) {
|
||||
vInput = cMath::MatrixMul(cMath::MatrixInverse(mpBody->GetLocalMatrix().GetRotation()), vInput);
|
||||
}
|
||||
|
||||
float fValue = GetAxisValue(mInputAxis, vInput);
|
||||
float fError = mfDestValue - fValue;
|
||||
|
||||
float fOutput = GetOutputValue(fError, fValue, afTimeStep);
|
||||
|
||||
if (mfMaxOutput > 0) {
|
||||
if (fOutput > 0)
|
||||
fOutput = cMath::Min(fOutput, mfMaxOutput);
|
||||
else
|
||||
fOutput = cMath::Max(fOutput, -mfMaxOutput);
|
||||
}
|
||||
|
||||
if (mbLogInfo)
|
||||
Log("%s | Input: %f Dest: %f Error: %f OutPut: %f\n", msName.c_str(), fValue, mfDestValue, fError, fOutput);
|
||||
|
||||
AddOutputValue(mOutputType, mOutputAxis, fOutput);
|
||||
|
||||
////////////////////////////////////////
|
||||
// Check if dest vale is reached
|
||||
if (mEndType == ePhysicsControllerEnd_OnDest && mpJoint) {
|
||||
if (ABS(fValue - mfDestValue) < kEpsilonf) {
|
||||
mbActive = false;
|
||||
iPhysicsController *pNext = mpJoint->GetController(msNextController);
|
||||
if (pNext)
|
||||
pNext->SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::SetActive(bool abX) {
|
||||
if (abX == mbActive)
|
||||
return;
|
||||
|
||||
mPidController.Reset();
|
||||
|
||||
mbActive = abX;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PROTECTED METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cVector3f iPhysicsController::GetInputValue(ePhysicsControllerInput aInput) {
|
||||
switch (aInput) {
|
||||
case ePhysicsControllerInput_AngularSpeed:
|
||||
return mpBody ? mpBody->GetAngularVelocity() : 0;
|
||||
case ePhysicsControllerInput_LinearSpeed:
|
||||
return mpBody ? mpBody->GetLinearVelocity() : 0;
|
||||
case ePhysicsControllerInput_JointAngle:
|
||||
return mpJoint ? mpJoint->GetAngle() : 0;
|
||||
case ePhysicsControllerInput_JointDist:
|
||||
return mpJoint ? mpJoint->GetDistance() : 0;
|
||||
case ePhysicsControllerInput_LastEnum:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
float iPhysicsController::GetOutputValue(float afError, float afInput, float afTimeStep) {
|
||||
if (mType == ePhysicsControllerType_Pid) {
|
||||
mPidController.p = mfA;
|
||||
mPidController.i = mfB;
|
||||
mPidController.d = mfC;
|
||||
|
||||
return mPidController.Output(afError, afTimeStep);
|
||||
} else {
|
||||
return afError * mfA - afInput * mfB;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::AddOutputValue(ePhysicsControllerOutput aOutput,
|
||||
ePhysicsControllerAxis aAxis,
|
||||
float afVal) {
|
||||
cVector3f vVec(0, 0, 0);
|
||||
|
||||
switch (aAxis) {
|
||||
case ePhysicsControllerAxis_X:
|
||||
vVec.x = afVal;
|
||||
break;
|
||||
case ePhysicsControllerAxis_Y:
|
||||
vVec.y = afVal;
|
||||
break;
|
||||
case ePhysicsControllerAxis_Z:
|
||||
vVec.z = afVal;
|
||||
break;
|
||||
case ePhysicsControllerAxis_LastEnum:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mbMulMassWithOutput)
|
||||
vVec = vVec * mpBody->GetMass();
|
||||
|
||||
// Set the output to body space
|
||||
vVec = cMath::MatrixMul(mpBody->GetLocalMatrix().GetRotation(), vVec);
|
||||
|
||||
switch (aOutput) {
|
||||
case ePhysicsControllerOutput_Torque:
|
||||
mpBody->AddTorque(vVec);
|
||||
break;
|
||||
case ePhysicsControllerOutput_Force:
|
||||
mpBody->AddForce(vVec);
|
||||
break;
|
||||
case ePhysicsControllerOutput_LastEnum:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
float iPhysicsController::GetAxisValue(ePhysicsControllerAxis aAxis, const cVector3f &avVec) {
|
||||
switch (aAxis) {
|
||||
case ePhysicsControllerAxis_X:
|
||||
return avVec.x;
|
||||
case ePhysicsControllerAxis_Y:
|
||||
return avVec.y;
|
||||
case ePhysicsControllerAxis_Z:
|
||||
return avVec.z;
|
||||
case ePhysicsControllerAxis_LastEnum:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerializeBase(cSaveData_iPhysicsController)
|
||||
kSerializeVar(msName, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mlBodyId, eSerializeType_Int32)
|
||||
kSerializeVar(mlJointId, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(mfA, eSerializeType_Float32)
|
||||
kSerializeVar(mfB, eSerializeType_Float32)
|
||||
kSerializeVar(mfC, eSerializeType_Float32)
|
||||
|
||||
kSerializeVar(mfDestValue, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxOutput, eSerializeType_Float32)
|
||||
|
||||
kSerializeVar(mbMulMassWithOutput, eSerializeType_Bool)
|
||||
|
||||
kSerializeVar(mType, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(mInputType, eSerializeType_Int32)
|
||||
kSerializeVar(mInputAxis, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(mOutputType, eSerializeType_Int32)
|
||||
kSerializeVar(mOutputAxis, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(mEndType, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(msNextController, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mbActive, eSerializeType_Bool)
|
||||
kSerializeVar(mbPaused, eSerializeType_Bool)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsController::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsController, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsController);
|
||||
|
||||
kSaveData_SaveTo(msName);
|
||||
|
||||
kSaveData_SaveTo(mfA);
|
||||
kSaveData_SaveTo(mfB);
|
||||
kSaveData_SaveTo(mfC);
|
||||
kSaveData_SaveTo(mfDestValue);
|
||||
kSaveData_SaveTo(mfMaxOutput);
|
||||
|
||||
kSaveData_SaveTo(mbMulMassWithOutput);
|
||||
|
||||
kSaveData_SaveTo(mType);
|
||||
kSaveData_SaveTo(mInputType);
|
||||
kSaveData_SaveTo(mInputAxis);
|
||||
kSaveData_SaveTo(mOutputType);
|
||||
kSaveData_SaveTo(mOutputAxis);
|
||||
kSaveData_SaveTo(mEndType);
|
||||
|
||||
kSaveData_SaveTo(msNextController);
|
||||
|
||||
kSaveData_SaveTo(mbActive);
|
||||
kSaveData_SaveTo(mbPaused);
|
||||
|
||||
kSaveData_SaveObject(mpBody, mlBodyId);
|
||||
kSaveData_SaveObject(mpJoint, mlJointId);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsController);
|
||||
|
||||
kSaveData_LoadFrom(msName);
|
||||
|
||||
kSaveData_LoadFrom(mfA);
|
||||
kSaveData_LoadFrom(mfB);
|
||||
kSaveData_LoadFrom(mfC);
|
||||
kSaveData_LoadFrom(mfDestValue);
|
||||
kSaveData_LoadFrom(mfMaxOutput);
|
||||
|
||||
kSaveData_LoadFrom(mbMulMassWithOutput);
|
||||
|
||||
mType = (ePhysicsControllerType)pData->mType;
|
||||
mInputType = (ePhysicsControllerInput)pData->mInputType;
|
||||
mInputAxis = (ePhysicsControllerAxis)pData->mInputAxis;
|
||||
mOutputType = (ePhysicsControllerOutput)pData->mOutputType;
|
||||
mOutputAxis = (ePhysicsControllerAxis)pData->mOutputAxis;
|
||||
mEndType = (ePhysicsControllerEnd)pData->mEndType;
|
||||
|
||||
kSaveData_LoadFrom(msNextController);
|
||||
|
||||
kSaveData_LoadFrom(mbActive);
|
||||
kSaveData_LoadFrom(mbPaused);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsController::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsController);
|
||||
|
||||
kSaveData_LoadObject(mpBody, mlBodyId, iPhysicsBody *);
|
||||
kSaveData_LoadObject(mpJoint, mlJointId, iPhysicsJoint *);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
234
engines/hpl1/engine/physics/PhysicsController.h
Normal file
234
engines/hpl1/engine/physics/PhysicsController.h
Normal file
@@ -0,0 +1,234 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_CONTROLLER_H
|
||||
#define HPL_PHYSICS_CONTROLLER_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/math/PidController.h"
|
||||
#include "hpl1/engine/math/Spring.h"
|
||||
|
||||
#include "hpl1/engine/game/SaveGame.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
enum ePhysicsControllerType {
|
||||
ePhysicsControllerType_Pid,
|
||||
ePhysicsControllerType_Spring,
|
||||
ePhysicsControllerType_LastEnum
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
enum ePhysicsControllerInput {
|
||||
ePhysicsControllerInput_JointAngle,
|
||||
ePhysicsControllerInput_JointDist,
|
||||
ePhysicsControllerInput_LinearSpeed,
|
||||
ePhysicsControllerInput_AngularSpeed,
|
||||
ePhysicsControllerInput_LastEnum
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
enum ePhysicsControllerOutput {
|
||||
ePhysicsControllerOutput_Force,
|
||||
ePhysicsControllerOutput_Torque,
|
||||
ePhysicsControllerOutput_LastEnum
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
enum ePhysicsControllerAxis {
|
||||
ePhysicsControllerAxis_X,
|
||||
ePhysicsControllerAxis_Y,
|
||||
ePhysicsControllerAxis_Z,
|
||||
ePhysicsControllerAxis_LastEnum
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
enum ePhysicsControllerEnd {
|
||||
ePhysicsControllerEnd_Null,
|
||||
ePhysicsControllerEnd_OnDest,
|
||||
ePhysicsControllerEnd_OnMin,
|
||||
ePhysicsControllerEnd_OnMax,
|
||||
ePhysicsControllerEnd_LastEnum
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
kSaveData_BaseClass(iPhysicsController) {
|
||||
kSaveData_ClassInit(iPhysicsController) public : tString msName;
|
||||
|
||||
int mlBodyId;
|
||||
int mlJointId;
|
||||
|
||||
float mfA;
|
||||
float mfB;
|
||||
float mfC;
|
||||
float mfDestValue;
|
||||
float mfMaxOutput;
|
||||
|
||||
bool mbMulMassWithOutput;
|
||||
|
||||
int mType;
|
||||
int mInputType;
|
||||
int mInputAxis;
|
||||
int mOutputType;
|
||||
int mOutputAxis;
|
||||
int mEndType;
|
||||
|
||||
tString msNextController;
|
||||
|
||||
bool mbActive;
|
||||
bool mbPaused;
|
||||
|
||||
iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame) { return NULL; }
|
||||
int GetSaveCreatePrio() { return 0; }
|
||||
};
|
||||
|
||||
//-------------------------------------------
|
||||
|
||||
class iPhysicsWorld;
|
||||
class iPhysicsJoint;
|
||||
class iPhysicsBody;
|
||||
|
||||
class iPhysicsController : public iSaveObject {
|
||||
typedef iSaveObject super;
|
||||
|
||||
public:
|
||||
iPhysicsController(const tString &asName, iPhysicsWorld *apWorld);
|
||||
virtual ~iPhysicsController();
|
||||
|
||||
void Update(float afTimeStep);
|
||||
|
||||
const tString &GetName() { return msName; }
|
||||
|
||||
void SetJoint(iPhysicsJoint *apJoint) { mpJoint = apJoint; }
|
||||
iPhysicsJoint *GetJoint() { return mpJoint; }
|
||||
void SetBody(iPhysicsBody *apBody) { mpBody = apBody; }
|
||||
iPhysicsBody *GetBody() { return mpBody; }
|
||||
|
||||
bool IsActive() { return mbActive; }
|
||||
void SetActive(bool abX);
|
||||
|
||||
/*
|
||||
* p in Pid and k in springs
|
||||
*/
|
||||
void SetA(float afA) { mfA = afA; }
|
||||
/*
|
||||
* i in Pid and b in springs
|
||||
*/
|
||||
void SetB(float afB) { mfB = afB; }
|
||||
/*
|
||||
* d in Pid and not used in springs
|
||||
*/
|
||||
void SetC(float afC) { mfC = afC; }
|
||||
|
||||
void SetPidIntegralSize(int alSize);
|
||||
|
||||
void SetType(ePhysicsControllerType aType) { mType = aType; }
|
||||
|
||||
void SetDestValue(float afX) { mfDestValue = afX; }
|
||||
float GetDestValue() { return mfDestValue; }
|
||||
|
||||
void SetMaxOutput(float afX) { mfMaxOutput = afX; }
|
||||
|
||||
void SetInputType(ePhysicsControllerInput aInput, ePhysicsControllerAxis aAxis) {
|
||||
mInputType = aInput;
|
||||
mInputAxis = aAxis;
|
||||
}
|
||||
|
||||
void SetOutputType(ePhysicsControllerOutput aOutput, ePhysicsControllerAxis aAxis) {
|
||||
mOutputType = aOutput;
|
||||
mOutputAxis = aAxis;
|
||||
}
|
||||
void SetMulMassWithOutput(bool abX) { mbMulMassWithOutput = abX; }
|
||||
|
||||
void SetEndType(ePhysicsControllerEnd aEnd) { mEndType = aEnd; }
|
||||
ePhysicsControllerEnd GetEndType() { return mEndType; }
|
||||
|
||||
void SetNextController(const tString &asName) { msNextController = asName; }
|
||||
const tString &GetNextController() { return msNextController; }
|
||||
|
||||
void SetLogInfo(bool abX) { mbLogInfo = abX; }
|
||||
|
||||
void SetPaused(bool abX) { mbPaused = abX; }
|
||||
|
||||
static bool mbUseInputMatrixFix;
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
cVector3f GetInputValue(ePhysicsControllerInput aInput);
|
||||
float GetOutputValue(float afError, float afInput, float afTimeStep);
|
||||
void AddOutputValue(ePhysicsControllerOutput aOutput, ePhysicsControllerAxis aAxis,
|
||||
float afVal);
|
||||
float GetAxisValue(ePhysicsControllerAxis aAxis, const cVector3f &avVec);
|
||||
|
||||
iPhysicsWorld *mpWorld;
|
||||
tString msName;
|
||||
|
||||
iPhysicsBody *mpBody;
|
||||
iPhysicsJoint *mpJoint;
|
||||
|
||||
float mfA, mfB, mfC;
|
||||
|
||||
float mfDestValue;
|
||||
float mfMaxOutput;
|
||||
|
||||
bool mbMulMassWithOutput;
|
||||
|
||||
ePhysicsControllerType mType;
|
||||
|
||||
ePhysicsControllerInput mInputType;
|
||||
ePhysicsControllerAxis mInputAxis;
|
||||
|
||||
ePhysicsControllerOutput mOutputType;
|
||||
ePhysicsControllerAxis mOutputAxis;
|
||||
|
||||
ePhysicsControllerEnd mEndType;
|
||||
|
||||
tString msNextController;
|
||||
|
||||
cPidControllerf mPidController;
|
||||
|
||||
bool mbActive;
|
||||
bool mbPaused;
|
||||
|
||||
bool mbLogInfo;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_CONTROLLER_H
|
||||
702
engines/hpl1/engine/physics/PhysicsJoint.cpp
Normal file
702
engines/hpl1/engine/physics/PhysicsJoint.cpp
Normal file
@@ -0,0 +1,702 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
|
||||
#include "hpl1/engine/physics/CollideShape.h"
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsController.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
#include "hpl1/engine/scene/SoundEntity.h"
|
||||
#include "hpl1/engine/sound/Sound.h"
|
||||
#include "hpl1/engine/sound/SoundChannel.h"
|
||||
#include "hpl1/engine/sound/SoundHandler.h"
|
||||
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
|
||||
#include "hpl1/engine/game/ScriptFuncs.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsJoint::iPhysicsJoint(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint)
|
||||
: msName(asName), mpParentBody(apParentBody), mpChildBody(apChildBody), mpWorld(apWorld) {
|
||||
mMaxLimit.msSound = "";
|
||||
mMinLimit.msSound = "";
|
||||
|
||||
if (apParentBody) {
|
||||
apParentBody->AddJoint(this);
|
||||
m_mtxParentBodySetup = apParentBody->GetLocalMatrix();
|
||||
} else {
|
||||
m_mtxParentBodySetup = cMatrixf::Identity;
|
||||
}
|
||||
|
||||
m_mtxPrevChild = cMatrixf::Identity;
|
||||
m_mtxPrevParent = cMatrixf::Identity;
|
||||
|
||||
apChildBody->AddJoint(this);
|
||||
m_mtxChildBodySetup = apChildBody->GetLocalMatrix();
|
||||
|
||||
cMatrixf m_mtxInvChild = cMath::MatrixInverse(apChildBody->GetLocalMatrix());
|
||||
mvLocalPivot = cMath::MatrixMul(m_mtxInvChild, avPivotPoint);
|
||||
mvStartPivotPoint = avPivotPoint;
|
||||
|
||||
msMoveSound = "";
|
||||
|
||||
mbHasCollided = false;
|
||||
mpSound = NULL;
|
||||
|
||||
mpCallback = NULL;
|
||||
|
||||
mbAutoDeleteCallback = false;
|
||||
|
||||
mpUserData = NULL;
|
||||
|
||||
mbBreakable = false;
|
||||
mfBreakForce = 0;
|
||||
msBreakSound = "";
|
||||
mbBroken = false;
|
||||
|
||||
mfStickyMinDistance = 0;
|
||||
mfStickyMaxDistance = 0;
|
||||
|
||||
mlLimitStepCount = 0;
|
||||
|
||||
mlSpeedCount = 0;
|
||||
|
||||
mbLimitAutoSleep = false;
|
||||
mfLimitAutoSleepDist = 0.02f;
|
||||
mlLimitAutoSleepNumSteps = 10;
|
||||
|
||||
// Log("Created joint '%s'\n",msName.c_str());
|
||||
}
|
||||
|
||||
iPhysicsJoint::~iPhysicsJoint() {
|
||||
if (mbAutoDeleteCallback && mpCallback)
|
||||
hplDelete(mpCallback);
|
||||
|
||||
// Destroy all controllers.
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
mpWorld->DestroyController(it->second);
|
||||
}
|
||||
|
||||
if (mpChildBody)
|
||||
mpChildBody->RemoveJoint(this);
|
||||
if (mpParentBody)
|
||||
mpParentBody->RemoveJoint(this);
|
||||
|
||||
if (mpSound)
|
||||
mpWorld->GetWorld3D()->DestroySoundEntity(mpSound);
|
||||
|
||||
// Log("Deleted joint '%s'\n",msName.c_str());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This should only be used by PhysicsBody.
|
||||
*/
|
||||
void iPhysicsJoint::RemoveBody(iPhysicsBody *apBody) {
|
||||
if (mpParentBody == apBody)
|
||||
mpParentBody = NULL;
|
||||
if (mpChildBody == apBody)
|
||||
mpChildBody = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::AddController(iPhysicsController *apController) {
|
||||
|
||||
// Add controller top map
|
||||
m_mapControllers.insert(tPhysicsControllerMap::value_type(apController->GetName(), apController));
|
||||
|
||||
// Set properties
|
||||
apController->SetBody(mpChildBody);
|
||||
apController->SetJoint(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsController *iPhysicsJoint::GetController(const tString &asName) {
|
||||
tPhysicsControllerMapIt it = m_mapControllers.find(asName);
|
||||
if (it == m_mapControllers.end())
|
||||
return NULL;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool iPhysicsJoint::ChangeController(const tString &asName) {
|
||||
iPhysicsController *pNewCtrl = GetController(asName);
|
||||
if (pNewCtrl == NULL)
|
||||
return false;
|
||||
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
iPhysicsController *pCtrl = it->second;
|
||||
|
||||
if (pCtrl == pNewCtrl) {
|
||||
pCtrl->SetActive(true);
|
||||
} else {
|
||||
pCtrl->SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::SetAllControllersPaused(bool abX) {
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
iPhysicsController *pCtrl = it->second;
|
||||
|
||||
pCtrl->SetPaused(abX);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cPhysicsControllerIterator iPhysicsJoint::GetControllerIterator() {
|
||||
return cPhysicsControllerIterator(&m_mapControllers);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PROTECTED METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::OnMaxLimit() {
|
||||
if (mbHasCollided == false && mpCallback) {
|
||||
mpCallback->OnMaxLimit(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Check if any of the controllers has a OnMax end.
|
||||
if (mbHasCollided == false) {
|
||||
// Log("OnMax!\n");
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
iPhysicsController *pCtrl = it->second;
|
||||
|
||||
// Log("Ctrl %s: %d\n",pCtrl->GetName().c_str(),(int)pCtrl->GetEndType());
|
||||
|
||||
if (pCtrl->IsActive() && pCtrl->GetEndType() == ePhysicsControllerEnd_OnMax) {
|
||||
pCtrl->SetActive(false);
|
||||
iPhysicsController *pNextCtrl = GetController(pCtrl->GetNextController());
|
||||
if (pNextCtrl)
|
||||
pNextCtrl->SetActive(true);
|
||||
else
|
||||
Warning("Controller '%s' does not exist in joint '%s'\n", pCtrl->GetNextController().c_str(), msName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LimitEffect(&mMaxLimit);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::OnMinLimit() {
|
||||
if (mbHasCollided == false && mpCallback) {
|
||||
mpCallback->OnMinLimit(this);
|
||||
}
|
||||
//////////////////////////////////////////////////
|
||||
// Check if any of the controllers has a OnMin end.
|
||||
if (mbHasCollided == false) {
|
||||
// Log("OnMin!\n");
|
||||
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
iPhysicsController *pCtrl = it->second;
|
||||
|
||||
if (pCtrl->IsActive() && pCtrl->GetEndType() == ePhysicsControllerEnd_OnMin) {
|
||||
pCtrl->SetActive(false);
|
||||
iPhysicsController *pNextCtrl = GetController(pCtrl->GetNextController());
|
||||
if (pNextCtrl)
|
||||
pNextCtrl->SetActive(true);
|
||||
else
|
||||
Warning("Controller '%s' does not exist in joint '%s'\n", pCtrl->GetNextController().c_str(), msName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LimitEffect(&mMinLimit);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::CalcSoundFreq(float afSpeed, float *apFreq, float *apVol) {
|
||||
float fAbsSpeed = ABS(afSpeed);
|
||||
float fFreq = 1;
|
||||
float fVolume = 1;
|
||||
|
||||
// Higher than middle
|
||||
if (fAbsSpeed >= mfMiddleMoveSpeed) {
|
||||
if (fAbsSpeed >= mfMaxMoveFreqSpeed) {
|
||||
fFreq = mfMaxMoveFreq;
|
||||
fVolume = mfMaxMoveVolume;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (fAbsSpeed - mfMiddleMoveSpeed) /
|
||||
(mfMaxMoveFreqSpeed - mfMiddleMoveSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMaxMoveFreq;
|
||||
fVolume = mfMiddleMoveVolume * (1 - fT) + fT * mfMaxMoveVolume;
|
||||
}
|
||||
}
|
||||
// Below middle
|
||||
else {
|
||||
if (fAbsSpeed <= mfMinMoveFreqSpeed) {
|
||||
fFreq = mfMinMoveFreq;
|
||||
fVolume = mfMinMoveVolume;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (mfMiddleMoveSpeed - fAbsSpeed) /
|
||||
(mfMiddleMoveSpeed - mfMinMoveFreqSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMinMoveFreq;
|
||||
fVolume = mfMiddleMoveVolume * (1 - fT) + fT * mfMinMoveVolume;
|
||||
}
|
||||
}
|
||||
|
||||
*apFreq = fFreq;
|
||||
*apVol = fVolume;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::OnPhysicsUpdate() {
|
||||
// Get the pivot point, if there is no parent, it is stuck.
|
||||
if (mpParentBody)
|
||||
mvPivotPoint = cMath::MatrixMul(mpChildBody->GetLocalMatrix(), mvLocalPivot);
|
||||
|
||||
cWorld3D *pWorld3D = mpWorld->GetWorld3D();
|
||||
if (pWorld3D == NULL)
|
||||
return;
|
||||
if (msMoveSound == "")
|
||||
return;
|
||||
|
||||
if (mpWorld->GetWorld3D()->GetSound()->GetSoundHandler()->GetSilent())
|
||||
return;
|
||||
|
||||
//////////////////////////////////////
|
||||
// Get the speed
|
||||
cVector3f vVel(0, 0, 0);
|
||||
// Linear
|
||||
if (mMoveSpeedType == ePhysicsJointSpeed_Linear) {
|
||||
if (mpParentBody) {
|
||||
vVel = mpChildBody->GetLinearVelocity() - mpParentBody->GetLinearVelocity();
|
||||
} else {
|
||||
vVel = mpChildBody->GetLinearVelocity();
|
||||
}
|
||||
}
|
||||
// Angular
|
||||
else {
|
||||
if (mpParentBody) {
|
||||
vVel = mpChildBody->GetAngularVelocity() - mpParentBody->GetAngularVelocity();
|
||||
} else {
|
||||
vVel = mpChildBody->GetAngularVelocity();
|
||||
}
|
||||
}
|
||||
|
||||
// Check so the body is not still
|
||||
if (mpParentBody) {
|
||||
if (m_mtxPrevChild == mpChildBody->GetLocalMatrix() &&
|
||||
m_mtxPrevParent == mpParentBody->GetLocalMatrix()) {
|
||||
vVel = 0;
|
||||
}
|
||||
m_mtxPrevChild = mpChildBody->GetLocalMatrix();
|
||||
m_mtxPrevParent = mpParentBody->GetLocalMatrix();
|
||||
} else {
|
||||
if (m_mtxPrevChild == mpChildBody->GetLocalMatrix()) {
|
||||
vVel = 0;
|
||||
}
|
||||
m_mtxPrevChild = mpChildBody->GetLocalMatrix();
|
||||
}
|
||||
|
||||
float fSpeed = vVel.Length();
|
||||
|
||||
if (pWorld3D->SoundEntityExists(mpSound) == false) {
|
||||
mpSound = NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Create and update sound if speed is high enough
|
||||
// Joint has sound
|
||||
if (mpSound) {
|
||||
// Log("Updating %s\n",mpSound->GetName().c_str());
|
||||
float fMin = cMath::Max(mfMinMoveSpeed - 0.2f, 0.1f);
|
||||
if (fSpeed <= fMin) {
|
||||
mpSound->FadeOut(4.3f);
|
||||
mpSound = NULL;
|
||||
} else {
|
||||
// Log("Getting entry!\n");
|
||||
cSoundEntry *pEntry = mpSound->GetSoundEntry(eSoundEntityType_Main);
|
||||
if (pEntry) {
|
||||
// Log("Update entry!\n");
|
||||
float fFreq, fVolume;
|
||||
CalcSoundFreq(fSpeed, &fFreq, &fVolume);
|
||||
|
||||
pEntry->mfNormalSpeed = fFreq;
|
||||
pEntry->mfNormalVolumeMul = fVolume;
|
||||
|
||||
// Log("Speed: %f Vol: %f Freq: %f\n",fSpeed,fVolume,fFreq);
|
||||
} else {
|
||||
// Log("Null entry!\n");
|
||||
}
|
||||
|
||||
mpSound->SetPosition(mvPivotPoint);
|
||||
}
|
||||
}
|
||||
//////////////////////
|
||||
// Joint has no sound
|
||||
else {
|
||||
/////////////////////////////
|
||||
// Speed is over limit
|
||||
if (fSpeed > mfMinMoveSpeed) {
|
||||
if (mlSpeedCount >= 3) {
|
||||
mlSpeedCount = 0;
|
||||
mpSound = pWorld3D->CreateSoundEntity("MoveSound", msMoveSound, true);
|
||||
if (mpSound) {
|
||||
mpSound->SetIsSaved(false);
|
||||
mpSound->FadeIn(3.3f);
|
||||
}
|
||||
// Log("Starting!\n");
|
||||
} else {
|
||||
mlSpeedCount++;
|
||||
}
|
||||
}
|
||||
/////////////////////////////
|
||||
// Speed is under limit
|
||||
else {
|
||||
mlSpeedCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::LimitEffect(cJointLimitEffect *pEffect) {
|
||||
cWorld3D *pWorld3D = mpWorld->GetWorld3D();
|
||||
|
||||
if (pWorld3D && pEffect->msSound != "") {
|
||||
cVector3f vVel(0, 0, 0);
|
||||
if (mpParentBody)
|
||||
vVel = mpChildBody->GetLinearVelocity() - mpParentBody->GetLinearVelocity();
|
||||
else
|
||||
vVel = mpChildBody->GetLinearVelocity();
|
||||
|
||||
float fSpeed = vVel.Length();
|
||||
if (fSpeed > pEffect->mfMaxSpeed)
|
||||
fSpeed = pEffect->mfMaxSpeed;
|
||||
|
||||
// Log("Speed: %f\n",fSpeed);
|
||||
|
||||
if (fSpeed >= pEffect->mfMinSpeed && mbHasCollided == false && pEffect->msSound != "") {
|
||||
float fVolume = (fSpeed - pEffect->mfMinSpeed) / (pEffect->mfMaxSpeed - pEffect->mfMinSpeed);
|
||||
|
||||
cSoundEntity *pSound = pWorld3D->CreateSoundEntity("LimitSound", pEffect->msSound, true);
|
||||
if (pSound) {
|
||||
pSound->SetVolume(fVolume);
|
||||
pSound->SetPosition(mpChildBody->GetLocalPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mbHasCollided = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::OnNoLimit() {
|
||||
mbHasCollided = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::Break() {
|
||||
mbBroken = true;
|
||||
mbBreakable = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool iPhysicsJoint::CheckBreakage() {
|
||||
if (mbBreakable == false)
|
||||
return false;
|
||||
|
||||
float fForcesSize = GetForce().Length();
|
||||
|
||||
if (fForcesSize >= mfBreakForce || mbBroken) {
|
||||
if (msBreakSound != "") {
|
||||
cWorld3D *pWorld3D = mpWorld->GetWorld3D();
|
||||
cSoundEntity *pSound = pWorld3D->CreateSoundEntity("BreakSound", msBreakSound, true);
|
||||
if (pSound)
|
||||
pSound->SetPosition(mvPivotPoint);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::CheckLimitAutoSleep(iPhysicsJoint *apJoint,
|
||||
const float afMin, const float afMax,
|
||||
const float afDist) {
|
||||
if (apJoint->mbLimitAutoSleep) {
|
||||
float fMinDiff = ABS(afMin - afDist);
|
||||
float fMaxDiff = ABS(afMax - afDist);
|
||||
|
||||
if (fMaxDiff < apJoint->mfLimitAutoSleepDist ||
|
||||
fMinDiff < apJoint->mfLimitAutoSleepDist) {
|
||||
if (apJoint->mlLimitStepCount >= apJoint->mlLimitAutoSleepNumSteps)
|
||||
apJoint->mpChildBody->DisableAfterSimulation();
|
||||
else
|
||||
apJoint->mlLimitStepCount++;
|
||||
} else {
|
||||
apJoint->mlLimitStepCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerializeBase(cJointLimitEffect)
|
||||
kSerializeVar(msSound, eSerializeType_String)
|
||||
kSerializeVar(mfMinSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxSpeed, eSerializeType_Float32)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerializeVirtual(cSaveData_iPhysicsJoint, iSaveData)
|
||||
kSerializeVar(msName, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mlParentBodyId, eSerializeType_Int32)
|
||||
kSerializeVar(mlChildBodyId, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(m_mtxParentBodySetup, eSerializeType_Matrixf)
|
||||
kSerializeVar(m_mtxChildBodySetup, eSerializeType_Matrixf)
|
||||
|
||||
kSerializeVar(mvPinDir, eSerializeType_Vector3f)
|
||||
kSerializeVar(mvStartPivotPoint, eSerializeType_Vector3f)
|
||||
|
||||
kSerializeClassContainer(mlstControllers, cSaveData_iPhysicsController, eSerializeType_Class)
|
||||
|
||||
kSerializeVar(mMaxLimit, eSerializeType_Class)
|
||||
kSerializeVar(mMinLimit, eSerializeType_Class)
|
||||
|
||||
kSerializeVar(msMoveSound, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mfMinMoveSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinMoveFreq, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinMoveFreqSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinMoveVolume, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxMoveFreq, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxMoveFreqSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxMoveVolume, eSerializeType_Float32)
|
||||
kSerializeVar(mfMiddleMoveSpeed, eSerializeType_Float32)
|
||||
kSerializeVar(mfMiddleMoveVolume, eSerializeType_Float32)
|
||||
kSerializeVar(mMoveSpeedType, eSerializeType_Int32)
|
||||
|
||||
kSerializeVar(mbBreakable, eSerializeType_Bool)
|
||||
kSerializeVar(mfBreakForce, eSerializeType_Float32)
|
||||
kSerializeVar(msBreakSound, eSerializeType_String)
|
||||
kSerializeVar(mbBroken, eSerializeType_Bool)
|
||||
|
||||
kSerializeVar(msCallbackMaxFunc, eSerializeType_String)
|
||||
kSerializeVar(msCallbackMinFunc, eSerializeType_String)
|
||||
|
||||
kSerializeVar(mbAutoDeleteCallback, eSerializeType_Bool)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsJoint::CreateSaveData() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsJoint);
|
||||
|
||||
//////////////////////////
|
||||
// Variables
|
||||
kSaveData_SaveTo(msName);
|
||||
|
||||
kSaveData_SaveTo(m_mtxParentBodySetup);
|
||||
kSaveData_SaveTo(m_mtxChildBodySetup);
|
||||
|
||||
kSaveData_SaveTo(mvPinDir);
|
||||
kSaveData_SaveTo(mvStartPivotPoint);
|
||||
|
||||
kSaveData_SaveTo(mMaxLimit);
|
||||
kSaveData_SaveTo(mMinLimit);
|
||||
kSaveData_SaveTo(msMoveSound);
|
||||
kSaveData_SaveTo(mfMinMoveSpeed);
|
||||
kSaveData_SaveTo(mfMinMoveFreq);
|
||||
kSaveData_SaveTo(mfMinMoveFreqSpeed);
|
||||
kSaveData_SaveTo(mfMinMoveVolume);
|
||||
kSaveData_SaveTo(mfMaxMoveFreq);
|
||||
kSaveData_SaveTo(mfMaxMoveFreqSpeed);
|
||||
kSaveData_SaveTo(mfMaxMoveVolume);
|
||||
kSaveData_SaveTo(mfMiddleMoveSpeed);
|
||||
kSaveData_SaveTo(mfMiddleMoveVolume);
|
||||
kSaveData_SaveTo(mMoveSpeedType);
|
||||
kSaveData_SaveTo(mbBreakable);
|
||||
kSaveData_SaveTo(mfBreakForce);
|
||||
kSaveData_SaveTo(msBreakSound);
|
||||
kSaveData_SaveTo(mbBroken);
|
||||
|
||||
kSaveData_SaveTo(mbAutoDeleteCallback);
|
||||
|
||||
// Callback
|
||||
if (mpCallback && mpCallback->IsScript()) {
|
||||
cScriptJointCallback *pScriptCallback = static_cast<cScriptJointCallback *>(mpCallback);
|
||||
pData->msCallbackMaxFunc = pScriptCallback->msMaxFunc;
|
||||
pData->msCallbackMinFunc = pScriptCallback->msMinFunc;
|
||||
} else {
|
||||
pData->msCallbackMaxFunc = "";
|
||||
pData->msCallbackMinFunc = "";
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Controllers
|
||||
pData->mlstControllers.Clear();
|
||||
tPhysicsControllerMapIt it = m_mapControllers.begin();
|
||||
for (; it != m_mapControllers.end(); ++it) {
|
||||
iPhysicsController *pController = it->second;
|
||||
cSaveData_iPhysicsController saveController;
|
||||
pController->SaveToSaveData(&saveController);
|
||||
|
||||
pData->mlstControllers.Add(saveController);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Pointers
|
||||
kSaveData_SaveObject(mpParentBody, mlParentBodyId);
|
||||
kSaveData_SaveObject(mpChildBody, mlChildBodyId);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsJoint);
|
||||
|
||||
//////////////////////////
|
||||
// Variables
|
||||
kSaveData_LoadFrom(msName);
|
||||
|
||||
kSaveData_LoadFrom(m_mtxParentBodySetup);
|
||||
kSaveData_LoadFrom(m_mtxChildBodySetup);
|
||||
|
||||
kSaveData_LoadFrom(mvPinDir);
|
||||
kSaveData_LoadFrom(mvStartPivotPoint);
|
||||
|
||||
kSaveData_LoadFrom(mMaxLimit);
|
||||
kSaveData_LoadFrom(mMinLimit);
|
||||
kSaveData_LoadFrom(msMoveSound);
|
||||
kSaveData_LoadFrom(mfMinMoveSpeed);
|
||||
kSaveData_LoadFrom(mfMinMoveFreq);
|
||||
kSaveData_LoadFrom(mfMinMoveFreqSpeed);
|
||||
kSaveData_LoadFrom(mfMinMoveVolume);
|
||||
kSaveData_LoadFrom(mfMaxMoveFreq);
|
||||
kSaveData_LoadFrom(mfMaxMoveFreqSpeed);
|
||||
kSaveData_LoadFrom(mfMaxMoveVolume);
|
||||
kSaveData_LoadFrom(mfMiddleMoveSpeed);
|
||||
kSaveData_LoadFrom(mfMiddleMoveVolume);
|
||||
kSaveData_LoadFrom(mbBreakable);
|
||||
kSaveData_LoadFrom(mfBreakForce);
|
||||
kSaveData_LoadFrom(msBreakSound);
|
||||
kSaveData_LoadFrom(mbBroken);
|
||||
mMoveSpeedType = (ePhysicsJointSpeed)pData->mMoveSpeedType;
|
||||
|
||||
kSaveData_LoadFrom(mbAutoDeleteCallback);
|
||||
|
||||
//////////////////////////
|
||||
// Controllers
|
||||
cContainerListIterator<cSaveData_iPhysicsController> CtrlIt = pData->mlstControllers.GetIterator();
|
||||
while (CtrlIt.HasNext()) {
|
||||
cSaveData_iPhysicsController &saveCtrl = CtrlIt.Next();
|
||||
iPhysicsController *pController = mpWorld->CreateController(saveCtrl.msName);
|
||||
pController->LoadFromSaveData(&saveCtrl);
|
||||
|
||||
AddController(pController);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJoint::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsJoint);
|
||||
|
||||
if (pData->msCallbackMaxFunc != "" || pData->msCallbackMinFunc != "") {
|
||||
cScriptJointCallback *pCallback = hplNew(cScriptJointCallback, (apGame->GetScene()));
|
||||
pCallback->msMaxFunc = pData->msCallbackMaxFunc;
|
||||
pCallback->msMinFunc = pData->msCallbackMinFunc;
|
||||
SetCallback(pCallback, true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
311
engines/hpl1/engine/physics/PhysicsJoint.h
Normal file
311
engines/hpl1/engine/physics/PhysicsJoint.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_JOINT_H
|
||||
#define HPL_PHYSICS_JOINT_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
#include "common/stablemap.h"
|
||||
|
||||
#include "hpl1/engine/game/SaveGame.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsController.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iPhysicsBody;
|
||||
class iPhysicsWorld;
|
||||
class cSoundEntity;
|
||||
class iPhysicsJoint;
|
||||
class iPhysicsController;
|
||||
|
||||
typedef Common::StableMap<tString, iPhysicsController *> tPhysicsControllerMap;
|
||||
typedef tPhysicsControllerMap::iterator tPhysicsControllerMapIt;
|
||||
|
||||
typedef cSTLMapIterator<iPhysicsController *, tPhysicsControllerMap, tPhysicsControllerMapIt> cPhysicsControllerIterator;
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
enum ePhysicsJointType {
|
||||
ePhysicsJointType_Ball,
|
||||
ePhysicsJointType_Hinge,
|
||||
ePhysicsJointType_Slider,
|
||||
ePhysicsJointType_Screw,
|
||||
ePhysicsJointType_LastEnum
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
enum ePhysicsJointSpeed {
|
||||
ePhysicsJointSpeed_Linear,
|
||||
ePhysicsJointSpeed_Angular,
|
||||
ePhysicsJointSpeed_LastEnum
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class cJointLimitEffect : public iSerializable {
|
||||
kSerializableClassInit(cJointLimitEffect) public : tString msSound;
|
||||
float mfMinSpeed;
|
||||
float mfMaxSpeed;
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJointCallback {
|
||||
public:
|
||||
virtual ~iPhysicsJointCallback() {}
|
||||
|
||||
virtual void OnMinLimit(iPhysicsJoint *apJoint) = 0;
|
||||
virtual void OnMaxLimit(iPhysicsJoint *apJoint) = 0;
|
||||
|
||||
// Ugly trick to support joint script callback.
|
||||
virtual bool IsScript() { return false; }
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_BaseClass(iPhysicsJoint) {
|
||||
kSaveData_ClassInit(iPhysicsJoint) public : tString msName;
|
||||
|
||||
int mlParentBodyId;
|
||||
int mlChildBodyId;
|
||||
|
||||
cMatrixf m_mtxParentBodySetup;
|
||||
cMatrixf m_mtxChildBodySetup;
|
||||
|
||||
cVector3f mvPinDir;
|
||||
cVector3f mvStartPivotPoint;
|
||||
|
||||
cContainerList<cSaveData_iPhysicsController> mlstControllers;
|
||||
|
||||
cJointLimitEffect mMaxLimit;
|
||||
cJointLimitEffect mMinLimit;
|
||||
|
||||
tString msMoveSound;
|
||||
|
||||
float mfMinMoveSpeed;
|
||||
float mfMinMoveFreq;
|
||||
float mfMinMoveFreqSpeed;
|
||||
float mfMinMoveVolume;
|
||||
float mfMaxMoveFreq;
|
||||
float mfMaxMoveFreqSpeed;
|
||||
float mfMaxMoveVolume;
|
||||
float mfMiddleMoveSpeed;
|
||||
float mfMiddleMoveVolume;
|
||||
int mMoveSpeedType;
|
||||
|
||||
bool mbBreakable;
|
||||
float mfBreakForce;
|
||||
tString msBreakSound;
|
||||
bool mbBroken;
|
||||
|
||||
tString msCallbackMaxFunc;
|
||||
tString msCallbackMinFunc;
|
||||
bool mbAutoDeleteCallback;
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJoint : public iSaveObject {
|
||||
typedef iSaveObject super;
|
||||
|
||||
public:
|
||||
iPhysicsJoint(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint);
|
||||
virtual ~iPhysicsJoint();
|
||||
|
||||
const tString &GetName() { return msName; }
|
||||
|
||||
iPhysicsBody *GetParentBody() { return mpParentBody; }
|
||||
iPhysicsBody *GetChildBody() { return mpChildBody; }
|
||||
|
||||
void RemoveBody(iPhysicsBody *apBody);
|
||||
|
||||
cVector3f GetPivotPoint() { return mvPivotPoint; }
|
||||
cVector3f GetPinDir() { return mvPinDir; }
|
||||
|
||||
virtual ePhysicsJointType GetType() = 0;
|
||||
|
||||
virtual void SetCollideBodies(bool abX) = 0;
|
||||
virtual bool GetCollideBodies() = 0;
|
||||
|
||||
virtual void SetStiffness(float afX) = 0;
|
||||
virtual float GetStiffness() = 0;
|
||||
|
||||
virtual cVector3f GetVelocity() = 0;
|
||||
virtual cVector3f GetAngularVelocity() = 0;
|
||||
virtual cVector3f GetForce() = 0;
|
||||
|
||||
virtual float GetDistance() = 0;
|
||||
virtual float GetAngle() = 0;
|
||||
|
||||
cJointLimitEffect *GetMaxLimit() { return &mMaxLimit; }
|
||||
cJointLimitEffect *GetMinLimit() { return &mMinLimit; }
|
||||
|
||||
void SetMoveSound(tString &asName) { msMoveSound = asName; }
|
||||
|
||||
void SetMoveSpeedType(ePhysicsJointSpeed aType) { mMoveSpeedType = aType; }
|
||||
void SetMinMoveSpeed(float afX) { mfMinMoveSpeed = afX; }
|
||||
void SetMinMoveFreq(float afX) { mfMinMoveFreq = afX; }
|
||||
void SetMinMoveFreqSpeed(float afX) { mfMinMoveFreqSpeed = afX; }
|
||||
void SetMinMoveVolume(float afX) { mfMinMoveVolume = afX; }
|
||||
void SetMaxMoveFreq(float afX) { mfMaxMoveFreq = afX; }
|
||||
void SetMaxMoveVolume(float afX) { mfMaxMoveVolume = afX; }
|
||||
void SetMaxMoveFreqSpeed(float afX) { mfMaxMoveFreqSpeed = afX; }
|
||||
void SetMiddleMoveSpeed(float afX) { mfMiddleMoveSpeed = afX; }
|
||||
void SetMiddleMoveVolume(float afX) { mfMiddleMoveVolume = afX; }
|
||||
|
||||
void SetCallback(iPhysicsJointCallback *apCallback, bool abAutoDelete) {
|
||||
mpCallback = apCallback;
|
||||
mbAutoDeleteCallback = abAutoDelete;
|
||||
}
|
||||
|
||||
iPhysicsJointCallback *GetCallback() { return mpCallback; }
|
||||
|
||||
bool CheckBreakage();
|
||||
|
||||
void SetBreakable(bool abX) { mbBreakable = abX; }
|
||||
bool IsBreakable() { return mbBreakable; }
|
||||
void SetBreakForce(float afForce) { mfBreakForce = afForce; }
|
||||
float GetBreakForce() { return mfBreakForce; }
|
||||
void SetBreakSound(const tString &asSound) { msBreakSound = asSound; }
|
||||
|
||||
void SetLimitAutoSleep(bool abX) { mbLimitAutoSleep = abX; }
|
||||
void SetLimitAutoSleepDist(float afX) { mfLimitAutoSleepDist = afX; }
|
||||
void SetLimitAutoSleepNumSteps(int alX) { mlLimitAutoSleepNumSteps = alX; }
|
||||
|
||||
bool GetLimitAutoSleep() { return mbLimitAutoSleep; }
|
||||
float GetLimitAutoSleepDist() { return mfLimitAutoSleepDist; }
|
||||
int GetLimitAutoSleepNumSteps() { return mlLimitAutoSleepNumSteps; }
|
||||
|
||||
void SetStickyMinDistance(float afX) { mfStickyMinDistance = afX; }
|
||||
void SetStickyMaxDistance(float afX) { mfStickyMaxDistance = afX; }
|
||||
float GetStickyMinDistance() { return mfStickyMinDistance; }
|
||||
float GetStickyMaxDistance() { return mfStickyMaxDistance; }
|
||||
|
||||
void Break();
|
||||
|
||||
bool IsBroken() { return mbBroken; }
|
||||
|
||||
void SetUserData(void *apUserData) { mpUserData = apUserData; }
|
||||
|
||||
void AddController(iPhysicsController *apController);
|
||||
iPhysicsController *GetController(const tString &asName);
|
||||
bool ChangeController(const tString &asName);
|
||||
cPhysicsControllerIterator GetControllerIterator();
|
||||
|
||||
void SetAllControllersPaused(bool abX);
|
||||
|
||||
void OnPhysicsUpdate();
|
||||
|
||||
void SetSound(cSoundEntity *apSound) { mpSound = apSound; }
|
||||
cSoundEntity *GetSound() { return mpSound; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
tString msName;
|
||||
|
||||
iPhysicsBody *mpParentBody;
|
||||
iPhysicsBody *mpChildBody;
|
||||
iPhysicsWorld *mpWorld;
|
||||
|
||||
cMatrixf m_mtxParentBodySetup;
|
||||
cMatrixf m_mtxChildBodySetup;
|
||||
|
||||
cVector3f mvPinDir;
|
||||
cVector3f mvPivotPoint;
|
||||
cVector3f mvStartPivotPoint;
|
||||
|
||||
cVector3f mvLocalPivot;
|
||||
|
||||
float mfStickyMinDistance;
|
||||
float mfStickyMaxDistance;
|
||||
|
||||
tPhysicsControllerMap m_mapControllers;
|
||||
|
||||
cJointLimitEffect mMaxLimit;
|
||||
cJointLimitEffect mMinLimit;
|
||||
|
||||
int mlSpeedCount;
|
||||
|
||||
cMatrixf m_mtxPrevChild;
|
||||
cMatrixf m_mtxPrevParent;
|
||||
|
||||
tString msMoveSound;
|
||||
|
||||
float mfMinMoveSpeed;
|
||||
float mfMinMoveFreq;
|
||||
float mfMinMoveFreqSpeed;
|
||||
float mfMinMoveVolume;
|
||||
float mfMaxMoveFreq;
|
||||
float mfMaxMoveFreqSpeed;
|
||||
float mfMaxMoveVolume;
|
||||
float mfMiddleMoveSpeed;
|
||||
float mfMiddleMoveVolume;
|
||||
ePhysicsJointSpeed mMoveSpeedType;
|
||||
|
||||
bool mbBreakable;
|
||||
float mfBreakForce;
|
||||
tString msBreakSound;
|
||||
bool mbBroken;
|
||||
|
||||
bool mbLimitAutoSleep;
|
||||
float mfLimitAutoSleepDist;
|
||||
int mlLimitAutoSleepNumSteps;
|
||||
|
||||
cSoundEntity *mpSound;
|
||||
bool mbHasCollided;
|
||||
|
||||
iPhysicsJointCallback *mpCallback;
|
||||
bool mbAutoDeleteCallback;
|
||||
|
||||
int mlLimitStepCount;
|
||||
|
||||
void *mpUserData;
|
||||
|
||||
static void CheckLimitAutoSleep(iPhysicsJoint *apJoint, const float afMin, const float afMax,
|
||||
const float afDist);
|
||||
|
||||
void OnMaxLimit();
|
||||
void OnMinLimit();
|
||||
void OnNoLimit();
|
||||
|
||||
void CalcSoundFreq(float afSpeed, float *apFreq, float *apVol);
|
||||
|
||||
void LimitEffect(cJointLimitEffect *pEffect);
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_JOINT_H
|
||||
125
engines/hpl1/engine/physics/PhysicsJointBall.cpp
Normal file
125
engines/hpl1/engine/physics/PhysicsJointBall.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJointBall.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerialize(cSaveData_iPhysicsJointBall, cSaveData_iPhysicsJoint)
|
||||
kSerializeVar(mfMaxConeAngle, eSerializeType_Float32)
|
||||
kSerializeVar(mfMaxTwistAngle, eSerializeType_Float32)
|
||||
kSerializeVar(mvConePin, eSerializeType_Vector3f)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveObject *cSaveData_iPhysicsJointBall::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
iPhysicsWorld *apWorld = apGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
|
||||
|
||||
cMatrixf mtxChildTemp, mtxParentTemp;
|
||||
|
||||
iPhysicsBody *pChildBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlChildBodyId));
|
||||
if (pChildBody == NULL)
|
||||
return NULL;
|
||||
|
||||
iPhysicsBody *pParentBody = NULL;
|
||||
if (mlParentBodyId > 0)
|
||||
pParentBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlParentBodyId));
|
||||
|
||||
mtxChildTemp = pChildBody->GetLocalMatrix();
|
||||
if (pParentBody)
|
||||
mtxParentTemp = pParentBody->GetLocalMatrix();
|
||||
|
||||
pChildBody->SetMatrix(m_mtxChildBodySetup);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(m_mtxParentBodySetup);
|
||||
|
||||
iPhysicsJointBall *pJoint = apWorld->CreateJointBall(msName, mvStartPivotPoint, pParentBody, pChildBody);
|
||||
pJoint->SetConeLimits(mvConePin, mfMaxConeAngle, mfMaxTwistAngle);
|
||||
|
||||
pChildBody->SetMatrix(mtxChildTemp);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(mtxParentTemp);
|
||||
|
||||
return pJoint;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int cSaveData_iPhysicsJointBall::GetSaveCreatePrio() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsJointBall::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsJointBall, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointBall::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsJointBall);
|
||||
|
||||
kSaveData_SaveTo(mfMaxConeAngle);
|
||||
kSaveData_SaveTo(mfMaxTwistAngle);
|
||||
kSaveData_SaveTo(mvConePin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointBall::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsJointBall);
|
||||
|
||||
kSaveData_LoadFrom(mfMaxConeAngle);
|
||||
kSaveData_LoadFrom(mfMaxTwistAngle);
|
||||
kSaveData_LoadFrom(mvConePin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointBall::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsJointBall);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
80
engines/hpl1/engine/physics/PhysicsJointBall.h
Normal file
80
engines/hpl1/engine/physics/PhysicsJointBall.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_JOINT_BALL_H
|
||||
#define HPL_PHYSICS_JOINT_BALL_H
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_ChildClass(iPhysicsJoint, iPhysicsJointBall) {
|
||||
kSaveData_ClassInit(iPhysicsJointBall) public : float mfMaxConeAngle;
|
||||
float mfMaxTwistAngle;
|
||||
cVector3f mvConePin;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJointBall : public iPhysicsJoint {
|
||||
typedef iPhysicsJoint super;
|
||||
|
||||
public:
|
||||
iPhysicsJointBall(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint)
|
||||
: iPhysicsJoint(asName, apParentBody, apChildBody, apWorld, avPivotPoint) {}
|
||||
virtual ~iPhysicsJointBall() {}
|
||||
|
||||
virtual void SetConeLimits(const cVector3f &avPin, float afMaxConeAngle, float afMaxTwistAngle) = 0;
|
||||
virtual cVector3f GetAngles() = 0;
|
||||
|
||||
float GetMaxConeAngle() { return mfMaxConeAngle; }
|
||||
float GetMaxTwistAngle() { return mfMaxTwistAngle; }
|
||||
cVector3f GetConePin() { return mvConePin; }
|
||||
|
||||
ePhysicsJointType GetType() { return ePhysicsJointType_Ball; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
float mfMaxConeAngle;
|
||||
float mfMaxTwistAngle;
|
||||
cVector3f mvConePin;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_JOINT_BALL_H
|
||||
119
engines/hpl1/engine/physics/PhysicsJointHinge.cpp
Normal file
119
engines/hpl1/engine/physics/PhysicsJointHinge.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJointHinge.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerialize(cSaveData_iPhysicsJointHinge, cSaveData_iPhysicsJoint)
|
||||
kSerializeVar(mfMaxAngle, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinAngle, eSerializeType_Float32)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveObject *cSaveData_iPhysicsJointHinge::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
iPhysicsWorld *apWorld = apGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
|
||||
|
||||
cMatrixf mtxChildTemp, mtxParentTemp;
|
||||
|
||||
iPhysicsBody *pChildBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlChildBodyId));
|
||||
if (pChildBody == NULL)
|
||||
return NULL;
|
||||
|
||||
iPhysicsBody *pParentBody = NULL;
|
||||
if (mlParentBodyId > 0)
|
||||
pParentBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlParentBodyId));
|
||||
|
||||
mtxChildTemp = pChildBody->GetLocalMatrix();
|
||||
if (pParentBody)
|
||||
mtxParentTemp = pParentBody->GetLocalMatrix();
|
||||
|
||||
pChildBody->SetMatrix(m_mtxChildBodySetup);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(m_mtxParentBodySetup);
|
||||
|
||||
iPhysicsJointHinge *pJoint = apWorld->CreateJointHinge(msName, mvStartPivotPoint, mvPinDir, pParentBody, pChildBody);
|
||||
|
||||
pChildBody->SetMatrix(mtxChildTemp);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(mtxParentTemp);
|
||||
|
||||
return pJoint;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int cSaveData_iPhysicsJointHinge::GetSaveCreatePrio() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsJointHinge::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsJointHinge, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointHinge::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsJointHinge);
|
||||
|
||||
kSaveData_SaveTo(mfMaxAngle);
|
||||
kSaveData_SaveTo(mfMinAngle);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointHinge::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsJointHinge);
|
||||
|
||||
kSaveData_LoadFrom(mfMaxAngle);
|
||||
kSaveData_LoadFrom(mfMinAngle);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointHinge::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsJointHinge);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
76
engines/hpl1/engine/physics/PhysicsJointHinge.h
Normal file
76
engines/hpl1/engine/physics/PhysicsJointHinge.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_JOINT_HINGE_H
|
||||
#define HPL_PHYSICS_JOINT_HINGE_H
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_ChildClass(iPhysicsJoint, iPhysicsJointHinge) {
|
||||
kSaveData_ClassInit(iPhysicsJointHinge) public : float mfMaxAngle;
|
||||
float mfMinAngle;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJointHinge : public iPhysicsJoint {
|
||||
typedef iPhysicsJoint super;
|
||||
|
||||
public:
|
||||
iPhysicsJointHinge(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint)
|
||||
: iPhysicsJoint(asName, apParentBody, apChildBody, apWorld, avPivotPoint) {}
|
||||
virtual ~iPhysicsJointHinge() {}
|
||||
|
||||
virtual void SetMaxAngle(float afAngle) = 0;
|
||||
virtual void SetMinAngle(float afAngle) = 0;
|
||||
virtual float GetMaxAngle() = 0;
|
||||
virtual float GetMinAngle() = 0;
|
||||
|
||||
ePhysicsJointType GetType() { return ePhysicsJointType_Hinge; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
float mfMaxAngle;
|
||||
float mfMinAngle;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_JOINT_HINGE_H
|
||||
122
engines/hpl1/engine/physics/PhysicsJointScrew.cpp
Normal file
122
engines/hpl1/engine/physics/PhysicsJointScrew.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJointScrew.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerialize(cSaveData_iPhysicsJointScrew, cSaveData_iPhysicsJoint)
|
||||
kSerializeVar(mfMaxDistance, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinDistance, eSerializeType_Float32)
|
||||
kSerializeVar(mvPin, eSerializeType_Vector3f)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveObject *cSaveData_iPhysicsJointScrew::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
iPhysicsWorld *apWorld = apGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
|
||||
|
||||
cMatrixf mtxChildTemp, mtxParentTemp;
|
||||
|
||||
iPhysicsBody *pChildBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlChildBodyId));
|
||||
if (pChildBody == NULL)
|
||||
return NULL;
|
||||
|
||||
iPhysicsBody *pParentBody = NULL;
|
||||
if (mlParentBodyId > 0)
|
||||
pParentBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlParentBodyId));
|
||||
|
||||
mtxChildTemp = pChildBody->GetLocalMatrix();
|
||||
if (pParentBody)
|
||||
mtxParentTemp = pParentBody->GetLocalMatrix();
|
||||
|
||||
pChildBody->SetMatrix(m_mtxChildBodySetup);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(m_mtxParentBodySetup);
|
||||
|
||||
iPhysicsJointScrew *pJoint = apWorld->CreateJointScrew(msName, mvStartPivotPoint, mvPinDir, pParentBody, pChildBody);
|
||||
|
||||
pChildBody->SetMatrix(mtxChildTemp);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(mtxParentTemp);
|
||||
|
||||
return pJoint;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int cSaveData_iPhysicsJointScrew::GetSaveCreatePrio() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsJointScrew::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsJointScrew, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointScrew::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsJointScrew);
|
||||
|
||||
kSaveData_SaveTo(mfMaxDistance);
|
||||
kSaveData_SaveTo(mfMinDistance);
|
||||
kSaveData_SaveTo(mvPin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointScrew::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsJointScrew);
|
||||
|
||||
kSaveData_LoadFrom(mfMaxDistance);
|
||||
kSaveData_LoadFrom(mfMinDistance);
|
||||
kSaveData_LoadFrom(mvPin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointScrew::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsJointScrew);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
85
engines/hpl1/engine/physics/PhysicsJointScrew.h
Normal file
85
engines/hpl1/engine/physics/PhysicsJointScrew.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_JOINT_SCREW_H
|
||||
#define HPL_PHYSICS_JOINT_SCREW_H
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_ChildClass(iPhysicsJoint, iPhysicsJointScrew) {
|
||||
kSaveData_ClassInit(iPhysicsJointScrew) public : float mfMaxDistance;
|
||||
float mfMinDistance;
|
||||
cVector3f mvPin;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJointScrew : public iPhysicsJoint {
|
||||
typedef iPhysicsJoint super;
|
||||
|
||||
public:
|
||||
iPhysicsJointScrew(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint)
|
||||
: iPhysicsJoint(asName, apParentBody, apChildBody, apWorld, avPivotPoint) {}
|
||||
virtual ~iPhysicsJointScrew() {}
|
||||
|
||||
/**
|
||||
* Set the maximum distance the bodies can be from each other, relative to the start dist between them
|
||||
* This is true if pin points towards the child.
|
||||
* In other words, distance increases as the distance between start pivot and current pivot
|
||||
* increases in the opposite direction of the pin.
|
||||
*/
|
||||
virtual void SetMaxDistance(float afX) = 0;
|
||||
virtual void SetMinDistance(float afX) = 0;
|
||||
virtual float GetMaxDistance() = 0;
|
||||
virtual float GetMinDistance() = 0;
|
||||
|
||||
ePhysicsJointType GetType() { return ePhysicsJointType_Screw; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
float mfMaxDistance;
|
||||
float mfMinDistance;
|
||||
|
||||
cVector3f mvPin;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_JOINT_SCREW_H
|
||||
122
engines/hpl1/engine/physics/PhysicsJointSlider.cpp
Normal file
122
engines/hpl1/engine/physics/PhysicsJointSlider.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJointSlider.h"
|
||||
|
||||
#include "hpl1/engine/game/Game.h"
|
||||
#include "hpl1/engine/scene/Scene.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SAVE OBJECT STUFF
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
kBeginSerialize(cSaveData_iPhysicsJointSlider, cSaveData_iPhysicsJoint)
|
||||
kSerializeVar(mfMaxDistance, eSerializeType_Float32)
|
||||
kSerializeVar(mfMinDistance, eSerializeType_Float32)
|
||||
kSerializeVar(mvPin, eSerializeType_Vector3f)
|
||||
kEndSerialize()
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveObject *cSaveData_iPhysicsJointSlider::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
iPhysicsWorld *apWorld = apGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
|
||||
|
||||
cMatrixf mtxChildTemp, mtxParentTemp;
|
||||
|
||||
iPhysicsBody *pChildBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlChildBodyId));
|
||||
if (pChildBody == NULL)
|
||||
return NULL;
|
||||
|
||||
iPhysicsBody *pParentBody = NULL;
|
||||
if (mlParentBodyId > 0)
|
||||
pParentBody = static_cast<iPhysicsBody *>(apSaveObjectHandler->Get(mlParentBodyId));
|
||||
|
||||
mtxChildTemp = pChildBody->GetLocalMatrix();
|
||||
if (pParentBody)
|
||||
mtxParentTemp = pParentBody->GetLocalMatrix();
|
||||
|
||||
pChildBody->SetMatrix(m_mtxChildBodySetup);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(m_mtxParentBodySetup);
|
||||
|
||||
iPhysicsJointSlider *pJoint = apWorld->CreateJointSlider(msName, mvStartPivotPoint, mvPinDir, pParentBody, pChildBody);
|
||||
|
||||
pChildBody->SetMatrix(mtxChildTemp);
|
||||
if (pParentBody)
|
||||
pParentBody->SetMatrix(mtxParentTemp);
|
||||
|
||||
return pJoint;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
int cSaveData_iPhysicsJointSlider::GetSaveCreatePrio() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iSaveData *iPhysicsJointSlider::CreateSaveData() {
|
||||
return hplNew(cSaveData_iPhysicsJointSlider, ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointSlider::SaveToSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_SaveToBegin(iPhysicsJointSlider);
|
||||
|
||||
kSaveData_SaveTo(mfMaxDistance);
|
||||
kSaveData_SaveTo(mfMinDistance);
|
||||
kSaveData_SaveTo(mvPin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointSlider::LoadFromSaveData(iSaveData *apSaveData) {
|
||||
kSaveData_LoadFromBegin(iPhysicsJointSlider);
|
||||
|
||||
kSaveData_LoadFrom(mfMaxDistance);
|
||||
kSaveData_LoadFrom(mfMinDistance);
|
||||
kSaveData_LoadFrom(mvPin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsJointSlider::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
|
||||
kSaveData_SetupBegin(iPhysicsJointSlider);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
87
engines/hpl1/engine/physics/PhysicsJointSlider.h
Normal file
87
engines/hpl1/engine/physics/PhysicsJointSlider.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_JOINT_SLIDER_H
|
||||
#define HPL_PHYSICS_JOINT_SLIDER_H
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
kSaveData_ChildClass(iPhysicsJoint, iPhysicsJointSlider) {
|
||||
kSaveData_ClassInit(iPhysicsJointSlider) public : float mfMaxDistance;
|
||||
float mfMinDistance;
|
||||
cVector3f mvPin;
|
||||
|
||||
virtual iSaveObject *CreateSaveObject(cSaveObjectHandler * apSaveObjectHandler, cGame * apGame);
|
||||
virtual int GetSaveCreatePrio();
|
||||
};
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
class iPhysicsJointSlider : public iPhysicsJoint {
|
||||
typedef iPhysicsJoint super;
|
||||
|
||||
public:
|
||||
iPhysicsJointSlider(const tString &asName, iPhysicsBody *apParentBody, iPhysicsBody *apChildBody,
|
||||
iPhysicsWorld *apWorld, const cVector3f &avPivotPoint)
|
||||
: iPhysicsJoint(asName, apParentBody, apChildBody, apWorld, avPivotPoint) {}
|
||||
virtual ~iPhysicsJointSlider() {}
|
||||
/**
|
||||
* Set the maximum distance the bodies can be from each other, relative to the start dist between them
|
||||
* This is true if pin points towards the child.
|
||||
* In other words, distance increases as the distance between start pivot and current pivot
|
||||
* increases in the opposite direction of the pin.
|
||||
*/
|
||||
virtual void SetMaxDistance(float afX) = 0;
|
||||
/**
|
||||
* Set the minimum distance the bodies can be from each other, relative to the start dist between them
|
||||
* This is true if pin points towards the child.
|
||||
*/
|
||||
virtual void SetMinDistance(float afX) = 0;
|
||||
virtual float GetMaxDistance() = 0;
|
||||
virtual float GetMinDistance() = 0;
|
||||
|
||||
ePhysicsJointType GetType() { return ePhysicsJointType_Slider; }
|
||||
|
||||
// SaveObject implementation
|
||||
virtual iSaveData *CreateSaveData();
|
||||
virtual void SaveToSaveData(iSaveData *apSaveData);
|
||||
virtual void LoadFromSaveData(iSaveData *apSaveData);
|
||||
virtual void SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame);
|
||||
|
||||
protected:
|
||||
float mfMaxDistance;
|
||||
float mfMinDistance;
|
||||
cVector3f mvPin;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_JOINT_SLIDER_H
|
||||
115
engines/hpl1/engine/physics/PhysicsMaterial.h
Normal file
115
engines/hpl1/engine/physics/PhysicsMaterial.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_MATERIAL_H
|
||||
#define HPL_PHYSICS_MATERIAL_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iPhysicsWorld;
|
||||
class cSurfaceData;
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
//! Enum the different combination modes
|
||||
//! This decides how two material properties are combined when colliding.
|
||||
//! If the two differ the enum with the highest num.
|
||||
enum ePhysicsMaterialCombMode {
|
||||
//! result = (value1 + value2)/2
|
||||
ePhysicsMaterialCombMode_Average = 0,
|
||||
//! result = min(value1, value2)
|
||||
ePhysicsMaterialCombMode_Min = 1,
|
||||
//! result = value1 * value2
|
||||
ePhysicsMaterialCombMode_Multiply = 2,
|
||||
//! result = max(value1, value2)
|
||||
ePhysicsMaterialCombMode_Max = 3,
|
||||
//! Internal.
|
||||
ePhysicsMaterialCombMode_LastEnum
|
||||
};
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
class cPhysicsContactData {
|
||||
public:
|
||||
cPhysicsContactData() {
|
||||
mfMaxContactNormalSpeed = 0;
|
||||
mfMaxContactTangentSpeed = 0;
|
||||
mvContactNormal = cVector3f(0, 0, 0);
|
||||
mvContactPosition = cVector3f(0, 0, 0);
|
||||
mvForce = cVector3f(0, 0, 0);
|
||||
}
|
||||
|
||||
float mfMaxContactNormalSpeed;
|
||||
float mfMaxContactTangentSpeed;
|
||||
cVector3f mvContactNormal;
|
||||
cVector3f mvContactPosition;
|
||||
cVector3f mvForce;
|
||||
};
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
class iPhysicsMaterial {
|
||||
public:
|
||||
iPhysicsMaterial(const tString &asName, iPhysicsWorld *apWorld)
|
||||
: msName(asName), mpWorld(apWorld), mpSurfaceData(NULL),
|
||||
mbPreloaded(false) {}
|
||||
virtual ~iPhysicsMaterial() {}
|
||||
|
||||
const tString &GetName() const { return msName; }
|
||||
|
||||
virtual void SetElasticity(float afElasticity) = 0;
|
||||
virtual float GetElasticity() const = 0;
|
||||
virtual void SetStaticFriction(float afElasticity) = 0;
|
||||
virtual float GetStaticFriction() const = 0;
|
||||
virtual void SetKineticFriction(float afElasticity) = 0;
|
||||
virtual float GetKineticFriction() const = 0;
|
||||
|
||||
virtual void SetFrictionCombMode(ePhysicsMaterialCombMode aMode) = 0;
|
||||
virtual ePhysicsMaterialCombMode GetFrictionCombMode() const = 0;
|
||||
virtual void SetElasticityCombMode(ePhysicsMaterialCombMode aMode) = 0;
|
||||
virtual ePhysicsMaterialCombMode GetElasticityCombMode() const = 0;
|
||||
|
||||
void SetSurfaceData(cSurfaceData *apData) { mpSurfaceData = apData; }
|
||||
cSurfaceData *GetSurfaceData() { return mpSurfaceData; }
|
||||
|
||||
void SetPreloaded(bool abX) { mbPreloaded = abX; }
|
||||
bool IsPreloaded() { return mbPreloaded; }
|
||||
|
||||
protected:
|
||||
iPhysicsWorld *mpWorld;
|
||||
tString msName;
|
||||
|
||||
bool mbPreloaded;
|
||||
|
||||
cSurfaceData *mpSurfaceData;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_MATERIAL_H
|
||||
410
engines/hpl1/engine/physics/PhysicsWorld.cpp
Normal file
410
engines/hpl1/engine/physics/PhysicsWorld.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
|
||||
#include "hpl1/engine/graphics/LowLevelGraphics.h"
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
#include "hpl1/engine/physics/CharacterBody.h"
|
||||
#include "hpl1/engine/physics/CollideShape.h"
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsController.h"
|
||||
#include "hpl1/engine/physics/PhysicsJoint.h"
|
||||
#include "hpl1/engine/physics/PhysicsMaterial.h"
|
||||
#include "hpl1/engine/physics/SurfaceData.h"
|
||||
#include "hpl1/engine/scene/PortalContainer.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
#include "hpl1/engine/system/System.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsWorld::iPhysicsWorld() {
|
||||
mbLogDebug = false;
|
||||
mbSaveContactPoints = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsWorld::~iPhysicsWorld() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::Update(float afTimeStep) {
|
||||
// Clear all contact points.
|
||||
mvContactPoints.clear();
|
||||
|
||||
////////////////////////////////////
|
||||
// Update controllers
|
||||
tPhysicsControllerListIt CtrlIt = mlstControllers.begin();
|
||||
for (; CtrlIt != mlstControllers.end(); ++CtrlIt) {
|
||||
iPhysicsController *pCtrl = *CtrlIt;
|
||||
|
||||
pCtrl->Update(afTimeStep);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Update character bodies
|
||||
// unsigned int lTime = GetApplicationTime();
|
||||
tCharacterBodyListIt CharIt = mlstCharBodies.begin();
|
||||
for (; CharIt != mlstCharBodies.end(); ++CharIt) {
|
||||
iCharacterBody *pBody = *CharIt;
|
||||
|
||||
// for(int i=0; i<20; ++i)
|
||||
{
|
||||
pBody->Update(afTimeStep); // 20.0f);
|
||||
}
|
||||
}
|
||||
// LogUpdate(" Updating chars took %d ms\n",mpWorld3D->GetSystem()->GetLowLevel()->GetTime() - lTime);
|
||||
|
||||
////////////////////////////////////
|
||||
// Update the rigid bodies before simulation.
|
||||
tPhysicsBodyListIt BodyIt = mlstBodies.begin();
|
||||
for (; BodyIt != mlstBodies.end(); ++BodyIt) {
|
||||
iPhysicsBody *pBody = *BodyIt;
|
||||
|
||||
pBody->UpdateBeforeSimulate(afTimeStep);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Simulate the physics
|
||||
// lTime = GetApplicationTime();
|
||||
Simulate(afTimeStep);
|
||||
// LogUpdate(" Updating lowlevel physics took %d ms\n",mpWorld3D->GetSystem()->GetLowLevel()->GetTime() - lTime);
|
||||
|
||||
////////////////////////////////////
|
||||
// Update the joints after simulation.
|
||||
tPhysicsJointListIt JointIt = mlstJoints.begin();
|
||||
for (; JointIt != mlstJoints.end();) {
|
||||
iPhysicsJoint *pJoint = *JointIt;
|
||||
|
||||
pJoint->OnPhysicsUpdate();
|
||||
|
||||
if (pJoint->CheckBreakage()) {
|
||||
JointIt = mlstJoints.erase(JointIt);
|
||||
hplDelete(pJoint);
|
||||
} else {
|
||||
++JointIt;
|
||||
}
|
||||
}
|
||||
////////////////////////////////////
|
||||
// Update the rigid bodies after simulation.
|
||||
BodyIt = mlstBodies.begin();
|
||||
for (; BodyIt != mlstBodies.end(); ++BodyIt) {
|
||||
iPhysicsBody *pBody = *BodyIt;
|
||||
|
||||
pBody->UpdateAfterSimulate(afTimeStep);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyShape(iCollideShape *apShape) {
|
||||
apShape->DecUserCount();
|
||||
if (apShape->HasUsers() == false) {
|
||||
STLFindAndDelete(mlstShapes, apShape);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyBody(iPhysicsBody *apBody) {
|
||||
// STLFindAndDelete(mlstBodies, apBody);
|
||||
tPhysicsBodyListIt it = mlstBodies.begin();
|
||||
for (; it != mlstBodies.end(); ++it) {
|
||||
iPhysicsBody *pBody = *it;
|
||||
if (pBody == apBody) {
|
||||
if (mpWorld3D)
|
||||
mpWorld3D->GetPortalContainer()->RemoveEntity(pBody);
|
||||
pBody->Destroy();
|
||||
hplDelete(pBody);
|
||||
mlstBodies.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iPhysicsBody *iPhysicsWorld::GetBody(const tString &asName) {
|
||||
return (iPhysicsBody *)STLFindByName(mlstBodies, asName);
|
||||
}
|
||||
|
||||
cPhysicsBodyIterator iPhysicsWorld::GetBodyIterator() {
|
||||
return cPhysicsBodyIterator(&mlstBodies);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::GetBodiesInBV(cBoundingVolume *apBV, tPhysicsBodyList *apBodyList) {
|
||||
tPhysicsBodyListIt BodyIt = mlstBodies.begin();
|
||||
for (; BodyIt != mlstBodies.end(); ++BodyIt) {
|
||||
iPhysicsBody *pBody = *BodyIt;
|
||||
if (pBody->GetMass() > 0 && cMath::CheckCollisionBV(*apBV, *pBody->GetBV())) {
|
||||
apBodyList->push_back(pBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iPhysicsWorld::EnableBodiesInBV(cBoundingVolume *apBV, bool abEnabled) {
|
||||
tPhysicsBodyListIt BodyIt = mlstBodies.begin();
|
||||
for (; BodyIt != mlstBodies.end(); ++BodyIt) {
|
||||
iPhysicsBody *pBody = *BodyIt;
|
||||
|
||||
if (pBody->GetMass() > 0 && cMath::CheckCollisionBV(*apBV, *pBody->GetBV())) {
|
||||
// quick fix for oscillation, might skip
|
||||
// if(pBody->GetJointNum()>0 && pBody->GetJoint(0)->GetLimitAutoSleep()) continue;
|
||||
|
||||
pBody->SetEnabled(abEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyJoint(iPhysicsJoint *apJoint) {
|
||||
STLFindAndDelete(mlstJoints, apJoint);
|
||||
}
|
||||
|
||||
iPhysicsJoint *iPhysicsWorld::GetJoint(const tString &asName) {
|
||||
return (iPhysicsJoint *)STLFindByName(mlstJoints, asName);
|
||||
}
|
||||
|
||||
cPhysicsJointIterator iPhysicsWorld::GetJointIterator() {
|
||||
return cPhysicsJointIterator(&mlstJoints);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyCharacterBody(iCharacterBody *apBody) {
|
||||
STLFindAndDelete(mlstCharBodies, apBody);
|
||||
}
|
||||
|
||||
iPhysicsBody *iPhysicsWorld::GetCharacterBody(const tString &asName) {
|
||||
return (iPhysicsBody *)STLFindByName(mlstCharBodies, asName);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsMaterial *iPhysicsWorld::GetMaterialFromName(const tString &asName) {
|
||||
tPhysicsMaterialMapIt it = m_mapMaterials.find(asName);
|
||||
if (it == m_mapMaterials.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iPhysicsMaterial *pMaterial = it->second;
|
||||
|
||||
if (pMaterial->IsPreloaded() == false && pMaterial->GetSurfaceData()) {
|
||||
pMaterial->SetPreloaded(true);
|
||||
pMaterial->GetSurfaceData()->PreloadData();
|
||||
}
|
||||
|
||||
return pMaterial;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cPhysicsMaterialIterator iPhysicsWorld::GetMaterialIterator() {
|
||||
return cPhysicsMaterialIterator(&m_mapMaterials);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyAll() {
|
||||
STLDeleteAll(mlstCharBodies);
|
||||
|
||||
// Bodies
|
||||
tPhysicsBodyListIt it = mlstBodies.begin();
|
||||
for (; it != mlstBodies.end(); ++it) {
|
||||
iPhysicsBody *pBody = *it;
|
||||
pBody->Destroy();
|
||||
hplDelete(pBody);
|
||||
}
|
||||
mlstBodies.clear();
|
||||
|
||||
STLDeleteAll(mlstShapes);
|
||||
STLDeleteAll(mlstJoints);
|
||||
STLDeleteAll(mlstControllers);
|
||||
STLMapDeleteAll(m_mapMaterials);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::AddSaveData(cSaveDataHandler *apHandler) {
|
||||
////////////////////////////////
|
||||
// Add all bodies
|
||||
tPhysicsBodyListIt BodyIt = mlstBodies.begin();
|
||||
for (; BodyIt != mlstBodies.end(); ++BodyIt) {
|
||||
iPhysicsBody *pBody = *BodyIt;
|
||||
|
||||
if (pBody->IsSaved()) {
|
||||
iSaveData *pData = pBody->CreateSaveData();
|
||||
pBody->SaveToSaveData(pData);
|
||||
apHandler->Add(pData);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Add all character bodies
|
||||
tCharacterBodyListIt CharIt = mlstCharBodies.begin();
|
||||
for (; CharIt != mlstCharBodies.end(); ++CharIt) {
|
||||
iCharacterBody *pBody = *CharIt;
|
||||
|
||||
if (pBody->IsSaved()) {
|
||||
iSaveData *pData = pBody->CreateSaveData();
|
||||
pBody->SaveToSaveData(pData);
|
||||
apHandler->Add(pData);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Add all joints
|
||||
tPhysicsJointListIt JointIt = mlstJoints.begin();
|
||||
for (; JointIt != mlstJoints.end(); ++JointIt) {
|
||||
iPhysicsJoint *pJoint = *JointIt;
|
||||
|
||||
if (pJoint->IsSaved()) {
|
||||
iSaveData *pData = pJoint->CreateSaveData();
|
||||
pJoint->SaveToSaveData(pData);
|
||||
apHandler->Add(pData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::DestroyController(iPhysicsController *apController) {
|
||||
STLFindAndDelete(mlstControllers, apController);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void iPhysicsWorld::RenderContactPoints(iLowLevelGraphics *apLowLevel, const cColor &aPointColor,
|
||||
const cColor &aLineColor) {
|
||||
for (size_t i = 0; i < mvContactPoints.size(); i++) {
|
||||
apLowLevel->DrawSphere(mvContactPoints[i].mvPoint, 0.2f, aPointColor);
|
||||
apLowLevel->DrawLine(mvContactPoints[i].mvPoint,
|
||||
mvContactPoints[i].mvNormal * mvContactPoints[i].mfDepth * 0.2f,
|
||||
aLineColor);
|
||||
// Log("Rendering\n");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
bool iPhysicsWorld::CheckShapeWorldCollision(cVector3f *apNewPos,
|
||||
iCollideShape *apShape, const cMatrixf &a_mtxTransform,
|
||||
iPhysicsBody *apSkipBody, bool abSkipStatic, bool abIsCharacter,
|
||||
iPhysicsWorldCollisionCallback *apCallback,
|
||||
bool abCollideCharacter,
|
||||
bool abDebug) {
|
||||
cCollideData collideData;
|
||||
|
||||
cVector3f vPushVec(0, 0, 0);
|
||||
bool bCollide = false;
|
||||
|
||||
cBoundingVolume boundingVolume = apShape->GetBoundingVolume();
|
||||
boundingVolume.SetTransform(cMath::MatrixMul(a_mtxTransform, boundingVolume.GetTransform()));
|
||||
|
||||
// Log("MAIN Position: %s Size: %s\n",boundingVolume.GetWorldCenter().ToString().c_str(),
|
||||
// boundingVolume.GetSize().ToString().c_str());
|
||||
|
||||
// if(abDebug)Log("--------------\n");
|
||||
|
||||
// tPhysicsBodyListIt it = mlstBodies.begin();
|
||||
// for(; it != mlstBodies.end(); ++it)
|
||||
cPortalContainerEntityIterator entIt = mpWorld3D->GetPortalContainer()->GetEntityIterator(&boundingVolume);
|
||||
while (entIt.HasNext()) {
|
||||
// iPhysicsBody *pBody = *it;
|
||||
iPhysicsBody *pBody = static_cast<iPhysicsBody *>(entIt.Next());
|
||||
|
||||
// if(abDebug) Log("Checking %s\n",pBody->GetName().c_str());
|
||||
|
||||
if (pBody->IsCharacter() && abCollideCharacter == false)
|
||||
continue;
|
||||
if (pBody->IsActive() == false)
|
||||
continue;
|
||||
if (pBody == apSkipBody)
|
||||
continue;
|
||||
if (abSkipStatic && pBody->GetMass() == 0)
|
||||
continue;
|
||||
if (abIsCharacter && pBody->GetCollideCharacter() == false)
|
||||
continue;
|
||||
if (abIsCharacter == false && pBody->GetCollide() == false)
|
||||
continue;
|
||||
|
||||
if (cMath::CheckCollisionBV(boundingVolume, *pBody->GetBV()) == false) {
|
||||
// if(abDebug) Log(" BV not collided\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
collideData.SetMaxSize(32);
|
||||
bool bRet = CheckShapeCollision(apShape, a_mtxTransform, pBody->GetShape(), pBody->GetLocalMatrix(),
|
||||
collideData, 32, true);
|
||||
|
||||
if (bRet) {
|
||||
// if(abDebug) Log(" Collided with '%s'\n",pBody->GetName().c_str());
|
||||
|
||||
if (apCallback)
|
||||
apCallback->OnCollision(pBody, &collideData);
|
||||
|
||||
for (int i = 0; i < collideData.mlNumOfPoints; i++) {
|
||||
cCollidePoint &point = collideData.mvContactPoints[i];
|
||||
|
||||
cVector3f vPush = point.mvNormal * point.mfDepth;
|
||||
|
||||
if (ABS(vPushVec.x) < ABS(vPush.x))
|
||||
vPushVec.x = vPush.x;
|
||||
if (ABS(vPushVec.y) < ABS(vPush.y))
|
||||
vPushVec.y = vPush.y;
|
||||
if (ABS(vPushVec.z) < ABS(vPush.z))
|
||||
vPushVec.z = vPush.z;
|
||||
}
|
||||
bCollide = true;
|
||||
}
|
||||
}
|
||||
// Log("--------------\n");
|
||||
|
||||
if (apNewPos)
|
||||
*apNewPos = a_mtxTransform.GetTranslation() + vPushVec;
|
||||
return bCollide;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
} // namespace hpl
|
||||
273
engines/hpl1/engine/physics/PhysicsWorld.h
Normal file
273
engines/hpl1/engine/physics/PhysicsWorld.h
Normal file
@@ -0,0 +1,273 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_PHYSICS_WORLD_H
|
||||
#define HPL_PHYSICS_WORLD_H
|
||||
|
||||
#include "hpl1/engine/graphics/GraphicsTypes.h"
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/system/SystemTypes.h"
|
||||
#include "common/stablemap.h"
|
||||
|
||||
#include "hpl1/engine/physics/CollideData.h"
|
||||
|
||||
#include "hpl1/engine/game/SaveGame.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
class iCollideShape;
|
||||
class iVertexBuffer;
|
||||
class iPhysicsBody;
|
||||
class iLowLevelGraphics;
|
||||
class iPhysicsMaterial;
|
||||
class iCharacterBody;
|
||||
class iPhysicsJoint;
|
||||
class iPhysicsJointBall;
|
||||
class iPhysicsJointHinge;
|
||||
class iPhysicsJointScrew;
|
||||
class iPhysicsJointSlider;
|
||||
class iPhysicsController;
|
||||
class cWorld3D;
|
||||
class cBoundingVolume;
|
||||
|
||||
typedef Common::List<iCollideShape *> tCollideShapeList;
|
||||
typedef tCollideShapeList::iterator tCollideShapeListIt;
|
||||
|
||||
typedef Common::Array<iCollideShape *> tCollideShapeVec;
|
||||
typedef tCollideShapeVec::iterator tCollideShapeVecIt;
|
||||
|
||||
typedef Common::List<iPhysicsBody *> tPhysicsBodyList;
|
||||
typedef tPhysicsBodyList::iterator tPhysicsBodyListIt;
|
||||
|
||||
typedef Common::List<iPhysicsJoint *> tPhysicsJointList;
|
||||
typedef tPhysicsJointList::iterator tPhysicsJointListIt;
|
||||
|
||||
typedef Common::List<iPhysicsController *> tPhysicsControllerList;
|
||||
typedef tPhysicsControllerList::iterator tPhysicsControllerListIt;
|
||||
|
||||
typedef Common::List<iCharacterBody *> tCharacterBodyList;
|
||||
typedef tCharacterBodyList::iterator tCharacterBodyListIt;
|
||||
|
||||
typedef Common::StableMap<tString, iPhysicsMaterial *> tPhysicsMaterialMap;
|
||||
typedef tPhysicsMaterialMap::iterator tPhysicsMaterialMapIt;
|
||||
|
||||
typedef cSTLMapIterator<iPhysicsMaterial *, tPhysicsMaterialMap, tPhysicsMaterialMapIt> cPhysicsMaterialIterator;
|
||||
|
||||
typedef cSTLIterator<iPhysicsBody *, tPhysicsBodyList, tPhysicsBodyListIt> cPhysicsBodyIterator;
|
||||
typedef cSTLIterator<iPhysicsJoint *, tPhysicsJointList, tPhysicsJointListIt> cPhysicsJointIterator;
|
||||
|
||||
enum ePhysicsAccuracy {
|
||||
ePhysicsAccuracy_Low,
|
||||
ePhysicsAccuracy_Medium,
|
||||
ePhysicsAccuracy_High,
|
||||
ePhysicsAccuracy_LastEnum
|
||||
};
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
struct cPhysicsRayParams {
|
||||
constexpr cPhysicsRayParams() {}
|
||||
float mfT = 0;
|
||||
float mfDist = 0;
|
||||
cVector3f mvNormal = {0, 0, 0};
|
||||
cVector3f mvPoint = {0, 0, 0};
|
||||
};
|
||||
|
||||
class iPhysicsRayCallback {
|
||||
public:
|
||||
virtual ~iPhysicsRayCallback() = default;
|
||||
virtual bool BeforeIntersect(iPhysicsBody *pBody) { return true; }
|
||||
virtual bool OnIntersect(iPhysicsBody *pBody, cPhysicsRayParams *apParams) = 0;
|
||||
};
|
||||
|
||||
class iPhysicsWorldCollisionCallback {
|
||||
public:
|
||||
virtual ~iPhysicsWorldCollisionCallback() = default;
|
||||
virtual void OnCollision(iPhysicsBody *apBody, cCollideData *apCollideData) = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
class iPhysicsWorld {
|
||||
public:
|
||||
iPhysicsWorld();
|
||||
virtual ~iPhysicsWorld();
|
||||
|
||||
//########################################################################################
|
||||
//! \name General
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
void Update(float afTimeStep);
|
||||
virtual void Simulate(float afTimeStep) = 0;
|
||||
|
||||
virtual void SetMaxTimeStep(float afTimeStep) = 0;
|
||||
virtual float GetMaxTimeStep() = 0;
|
||||
|
||||
virtual void SetWorldSize(const cVector3f &avMin, const cVector3f &avMax) = 0;
|
||||
virtual cVector3f GetWorldSizeMin() = 0;
|
||||
virtual cVector3f GetWorldSizeMax() = 0;
|
||||
|
||||
virtual void SetGravity(const cVector3f &avGravity) = 0;
|
||||
virtual cVector3f GetGravity() = 0;
|
||||
|
||||
virtual void SetAccuracyLevel(ePhysicsAccuracy aAccuracy) = 0;
|
||||
virtual ePhysicsAccuracy GetAccuracyLevel() = 0;
|
||||
//! @}
|
||||
|
||||
//########################################################################################
|
||||
//! \name Shapes
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
virtual iCollideShape *CreateNullShape() = 0;
|
||||
virtual iCollideShape *CreateBoxShape(const cVector3f &avSize, cMatrixf *apOffsetMtx) = 0;
|
||||
virtual iCollideShape *CreateSphereShape(const cVector3f &avRadii, cMatrixf *apOffsetMtx) = 0;
|
||||
virtual iCollideShape *CreateCylinderShape(float afRadius, float afHeight, cMatrixf *apOffsetMtx) = 0;
|
||||
virtual iCollideShape *CreateCapsuleShape(float afRadius, float afHeight, cMatrixf *apOffsetMtx) = 0;
|
||||
virtual iCollideShape *CreateMeshShape(iVertexBuffer *apVtxBuffer) = 0;
|
||||
virtual iCollideShape *CreateCompundShape(tCollideShapeVec &avShapes) = 0;
|
||||
void DestroyShape(iCollideShape *apShape);
|
||||
|
||||
//! @}
|
||||
|
||||
//########################################################################################
|
||||
//! \name Joints
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
virtual iPhysicsJointBall *CreateJointBall(const tString &asName,
|
||||
const cVector3f &avPivotPoint,
|
||||
iPhysicsBody *apParentBody, iPhysicsBody *apChildBody) = 0;
|
||||
virtual iPhysicsJointHinge *CreateJointHinge(const tString &asName,
|
||||
const cVector3f &avPivotPoint, const cVector3f &avPinDir,
|
||||
iPhysicsBody *apParentBody, iPhysicsBody *apChildBody) = 0;
|
||||
virtual iPhysicsJointSlider *CreateJointSlider(const tString &asName,
|
||||
const cVector3f &avPivotPoint, const cVector3f &avPinDir,
|
||||
iPhysicsBody *apParentBody, iPhysicsBody *apChildBody) = 0;
|
||||
virtual iPhysicsJointScrew *CreateJointScrew(const tString &asName,
|
||||
const cVector3f &avPivotPoint, const cVector3f &avPinDir,
|
||||
iPhysicsBody *apParentBody, iPhysicsBody *apChildBody) = 0;
|
||||
void DestroyJoint(iPhysicsJoint *apJoint);
|
||||
iPhysicsJoint *GetJoint(const tString &asName);
|
||||
cPhysicsJointIterator GetJointIterator();
|
||||
|
||||
//! @}
|
||||
|
||||
//########################################################################################
|
||||
//! \name Materials
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
virtual iPhysicsMaterial *CreateMaterial(const tString &asName) = 0;
|
||||
iPhysicsMaterial *GetMaterialFromName(const tString &asName);
|
||||
cPhysicsMaterialIterator GetMaterialIterator();
|
||||
|
||||
//! @}
|
||||
|
||||
//########################################################################################
|
||||
//! \name Bodies
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
virtual iPhysicsBody *CreateBody(const tString &asName, iCollideShape *apShape) = 0;
|
||||
void DestroyBody(iPhysicsBody *apBody);
|
||||
iPhysicsBody *GetBody(const tString &asName);
|
||||
cPhysicsBodyIterator GetBodyIterator();
|
||||
|
||||
virtual iCharacterBody *CreateCharacterBody(const tString &asName, const cVector3f &avSize) = 0;
|
||||
void DestroyCharacterBody(iCharacterBody *apBody);
|
||||
iPhysicsBody *GetCharacterBody(const tString &asName);
|
||||
|
||||
void GetBodiesInBV(cBoundingVolume *apBV, tPhysicsBodyList *apBodyList);
|
||||
void EnableBodiesInBV(cBoundingVolume *apBV, bool abEnabled);
|
||||
|
||||
//! @}
|
||||
|
||||
//########################################################################################
|
||||
//! \name Tools
|
||||
//########################################################################################
|
||||
//! @{
|
||||
|
||||
void SetLogDebug(bool abX) { mbLogDebug = abX; }
|
||||
bool GetLogDebug() { return mbLogDebug; }
|
||||
|
||||
void AddSaveData(cSaveDataHandler *apHandler);
|
||||
|
||||
virtual iPhysicsController *CreateController(const tString &asName) = 0;
|
||||
void DestroyController(iPhysicsController *apController);
|
||||
|
||||
tCollidePointVec *GetContactPoints() { return &mvContactPoints; }
|
||||
void SetSaveContactPoints(bool abX) { mbSaveContactPoints = abX; }
|
||||
bool GetSaveContactPoints() { return mbSaveContactPoints; }
|
||||
void RenderContactPoints(iLowLevelGraphics *apLowLevel, const cColor &aPointColor,
|
||||
const cColor &aLineColor);
|
||||
|
||||
virtual void CastRay(iPhysicsRayCallback *apCallback,
|
||||
const cVector3f &avOrigin, const cVector3f &avEnd,
|
||||
bool abCalcDist, bool abCalcNormal, bool abCalcPoint,
|
||||
bool abUsePrefilter = false) = 0;
|
||||
|
||||
virtual void RenderDebugGeometry(iLowLevelGraphics *apLowLevel, const cColor &aColor) = 0;
|
||||
|
||||
virtual bool CheckShapeCollision(iCollideShape *apShapeA, const cMatrixf &a_mtxA,
|
||||
iCollideShape *apShapeB, const cMatrixf &a_mtxB,
|
||||
cCollideData &aCollideData, int alMaxPoints,
|
||||
bool correctNormalDirection = false) = 0;
|
||||
|
||||
bool CheckShapeWorldCollision(cVector3f *apNewPos,
|
||||
iCollideShape *apShape, const cMatrixf &a_mtxTransform,
|
||||
iPhysicsBody *apSkipBody = NULL, bool abSkipStatic = false,
|
||||
bool abIsCharacter = false,
|
||||
iPhysicsWorldCollisionCallback *apCallback = NULL,
|
||||
bool abCollideCharacter = true,
|
||||
bool abDebug = false);
|
||||
|
||||
void DestroyAll();
|
||||
|
||||
cWorld3D *GetWorld3D() { return mpWorld3D; }
|
||||
void SetWorld3D(cWorld3D *apWorld3D) { mpWorld3D = apWorld3D; }
|
||||
//! @}
|
||||
|
||||
protected:
|
||||
tCollideShapeList mlstShapes;
|
||||
tPhysicsBodyList mlstBodies;
|
||||
tCharacterBodyList mlstCharBodies;
|
||||
tPhysicsMaterialMap m_mapMaterials;
|
||||
tPhysicsJointList mlstJoints;
|
||||
tPhysicsControllerList mlstControllers;
|
||||
cWorld3D *mpWorld3D;
|
||||
|
||||
bool mbLogDebug;
|
||||
|
||||
tCollidePointVec mvContactPoints;
|
||||
bool mbSaveContactPoints;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_PHYSICS_WORLD_H
|
||||
598
engines/hpl1/engine/physics/SurfaceData.cpp
Normal file
598
engines/hpl1/engine/physics/SurfaceData.cpp
Normal file
@@ -0,0 +1,598 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#include "hpl1/engine/physics/SurfaceData.h"
|
||||
|
||||
#include "hpl1/engine/math/Math.h"
|
||||
#include "hpl1/engine/physics/Physics.h"
|
||||
#include "hpl1/engine/physics/PhysicsBody.h"
|
||||
#include "hpl1/engine/physics/PhysicsWorld.h"
|
||||
#include "hpl1/engine/system/low_level_system.h"
|
||||
|
||||
#include "hpl1/engine/scene/SoundEntity.h"
|
||||
#include "hpl1/engine/scene/World3D.h"
|
||||
#include "hpl1/engine/sound/Sound.h"
|
||||
#include "hpl1/engine/sound/SoundChannel.h"
|
||||
#include "hpl1/engine/sound/SoundHandler.h"
|
||||
|
||||
#include "hpl1/engine/resources/ParticleManager.h"
|
||||
#include "hpl1/engine/resources/Resources.h"
|
||||
#include "hpl1/engine/resources/SoundEntityManager.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CONSTRUCTORS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSurfaceData::cSurfaceData(const tString &asName, cPhysics *apPhysics, cResources *apResources) {
|
||||
msName = asName;
|
||||
mpPhysics = apPhysics;
|
||||
mpResources = apResources;
|
||||
|
||||
// Setup default properties
|
||||
mFrictionMode = ePhysicsMaterialCombMode_Average;
|
||||
mElasticityMode = ePhysicsMaterialCombMode_Average;
|
||||
|
||||
mfElasticity = 0.5f;
|
||||
mfStaticFriction = 0.3f;
|
||||
mfKineticFriction = 0.3f;
|
||||
|
||||
mlPriority = 0;
|
||||
|
||||
mfMinScrapeSpeed = 0.6f;
|
||||
mfMinScrapeFreq = 0.7f;
|
||||
mfMinScrapeFreqSpeed = 1;
|
||||
mfMaxScrapeFreq = 2;
|
||||
mfMaxScrapeFreqSpeed = 3;
|
||||
mfMiddleScrapeSpeed = 2;
|
||||
msScrapeSoundName = "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSurfaceData::~cSurfaceData() {
|
||||
STLDeleteAll(mvImpactData);
|
||||
STLDeleteAll(mvHitData);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::OnImpact(float afSpeed, const cVector3f &avPos, int alContacts, iPhysicsBody *apBody) {
|
||||
if (mpPhysics->CanPlayImpact() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
apBody->SetHasImpact(true);
|
||||
|
||||
cWorld3D *pWorld = mpPhysics->GetGameWorld();
|
||||
if (pWorld == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cSurfaceImpactData *pData = NULL;
|
||||
for (size_t i = 0; i < mvImpactData.size(); i++) {
|
||||
if (mvImpactData[i]->GetMinSpeed() <= afSpeed) {
|
||||
pData = mvImpactData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pData == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pData->GetSoundName() != "") {
|
||||
mpPhysics->AddImpact();
|
||||
|
||||
cSoundEntity *pEntity = pWorld->CreateSoundEntity("Impact",
|
||||
pData->GetSoundName(), true);
|
||||
if (pEntity) {
|
||||
// TODO: Offset the sound a bit so that it is not played inside a static object.
|
||||
pEntity->SetPosition(avPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::OnSlide(float afSpeed, const cVector3f &avPos, int alContacts, iPhysicsBody *apBody,
|
||||
iPhysicsBody *apSlideAgainstBody) {
|
||||
if (alContacts < mlMinScrapeContacts)
|
||||
return;
|
||||
|
||||
// Make sure that only one body can update the scrape.
|
||||
if (apBody->GetScrapeBody() != NULL &&
|
||||
apSlideAgainstBody != apBody->GetScrapeBody()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cWorld3D *pWorld = mpPhysics->GetGameWorld();
|
||||
if (pWorld == NULL)
|
||||
return;
|
||||
|
||||
cSoundHandler *pSoundHandler = pWorld->GetSound()->GetSoundHandler();
|
||||
if (pSoundHandler->GetSilent())
|
||||
return;
|
||||
|
||||
// Check if sound exist in world.
|
||||
if (pWorld->SoundEntityExists(apBody->GetScrapeSoundEntity()) == false) {
|
||||
apBody->SetScrapeSoundEntity(NULL);
|
||||
}
|
||||
|
||||
// Check if body is still, in that case stop set speed to 0
|
||||
if (apBody->GetMass() != 0) {
|
||||
if (apBody->GetPreveScrapeMatrix() == apBody->GetLocalMatrix()) {
|
||||
afSpeed = 0;
|
||||
}
|
||||
apBody->SetPreveScrapeMatrix(apBody->GetLocalMatrix());
|
||||
}
|
||||
|
||||
// If the body all ready has a scrape sound
|
||||
if (apBody->GetScrapeSoundEntity() != NULL) {
|
||||
// check if the sound should be stopped
|
||||
float fMin = cMath::Max(mfMinScrapeSpeed - 0.7f, 0.02f);
|
||||
if (ABS(afSpeed) < fMin) {
|
||||
apBody->GetScrapeSoundEntity()->FadeOut(4.3f);
|
||||
apBody->SetScrapeSoundEntity(NULL);
|
||||
apBody->SetScrapeBody(NULL);
|
||||
// Log("Stopped scrape '%s' %d on body '%s' IN SURFACEDATA!\n",msScrapeSoundName.c_str(),
|
||||
// (size_t)apBody->GetScrapeSoundEntity(),
|
||||
// apBody->GetName().c_str());
|
||||
} else {
|
||||
apBody->SetHasSlide(true);
|
||||
|
||||
// Change frequency according to speed.
|
||||
float fAbsSpeed = ABS(afSpeed);
|
||||
float fFreq = 1;
|
||||
|
||||
// Higher than middle
|
||||
if (fAbsSpeed >= mfMiddleScrapeSpeed) {
|
||||
if (fAbsSpeed >= mfMaxScrapeFreqSpeed) {
|
||||
fFreq = mfMaxScrapeFreq;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (fAbsSpeed - mfMiddleScrapeSpeed) /
|
||||
(mfMaxScrapeFreqSpeed - mfMiddleScrapeSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMaxScrapeFreq;
|
||||
}
|
||||
}
|
||||
// Below middle
|
||||
else {
|
||||
if (fAbsSpeed <= mfMinScrapeFreqSpeed) {
|
||||
fFreq = mfMinScrapeFreq;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (mfMiddleScrapeSpeed - fAbsSpeed) /
|
||||
(mfMiddleScrapeSpeed - mfMinScrapeFreqSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMinScrapeFreq;
|
||||
}
|
||||
}
|
||||
|
||||
// Log("Speed: %f Freq: %f\n",fAbsSpeed,fFreq);
|
||||
cSoundEntry *pEntry = apBody->GetScrapeSoundEntity()->GetSoundEntry(eSoundEntityType_Main);
|
||||
if (pEntry) {
|
||||
pEntry->mfNormalSpeed = fFreq;
|
||||
apBody->GetScrapeSoundEntity()->SetPosition(avPos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mfMinScrapeSpeed <= ABS(afSpeed) && msScrapeSoundName != "") {
|
||||
apBody->SetHasSlide(true);
|
||||
|
||||
cSoundEntity *pEntity = pWorld->CreateSoundEntity("Scrape",
|
||||
msScrapeSoundName, true);
|
||||
if (pEntity) {
|
||||
pEntity->FadeIn(3.3f);
|
||||
pEntity->SetPosition(avPos);
|
||||
|
||||
pEntity->SetIsSaved(false);
|
||||
|
||||
apBody->SetScrapeSoundEntity(pEntity);
|
||||
apBody->SetScrapeBody(apSlideAgainstBody);
|
||||
|
||||
// Log("Starting scrape '%s' %d on body '%s'\n",msScrapeSoundName.c_str(),
|
||||
// (size_t)pEntity,
|
||||
// apBody->GetName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::CreateImpactEffect(float afSpeed, const cVector3f &avPos, int alContacts,
|
||||
cSurfaceData *apSecondSurface) {
|
||||
if (afSpeed == 0)
|
||||
return;
|
||||
|
||||
cSurfaceImpactData *pDataA = NULL;
|
||||
cSurfaceImpactData *pDataB = NULL;
|
||||
|
||||
cWorld3D *pWorld = mpPhysics->GetGameWorld();
|
||||
if (pWorld == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cSoundHandler *pSoundHandler = pWorld->GetSound()->GetSoundHandler();
|
||||
if (pSoundHandler->GetSilent())
|
||||
return;
|
||||
|
||||
/////////////////////////////
|
||||
// Get first surface
|
||||
for (size_t i = 0; i < mvImpactData.size(); i++) {
|
||||
if (mvImpactData[i]->GetMinSpeed() <= afSpeed) {
|
||||
pDataA = mvImpactData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// Get second surface
|
||||
if (apSecondSurface != this && apSecondSurface != NULL) {
|
||||
for (size_t i = 0; i < apSecondSurface->mvImpactData.size(); i++) {
|
||||
if (apSecondSurface->mvImpactData[i]->GetMinSpeed() <= afSpeed) {
|
||||
pDataB = apSecondSurface->mvImpactData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tString sPS = "";
|
||||
|
||||
if (pDataA && !pDataB) {
|
||||
sPS = pDataA->GetPSName();
|
||||
} else if (!pDataA && pDataB) {
|
||||
sPS = pDataB->GetPSName();
|
||||
} else if (pDataA && pDataB) {
|
||||
if (pDataA->GetPSPrio() >= pDataB->GetPSPrio())
|
||||
sPS = pDataA->GetPSName();
|
||||
else
|
||||
sPS = pDataB->GetPSName();
|
||||
}
|
||||
|
||||
if (sPS != "") {
|
||||
cMatrixf mtxPos = cMath::MatrixTranslate(avPos);
|
||||
pWorld->CreateParticleSystem("ImpactPS", sPS, 1, mtxPos);
|
||||
|
||||
// Log("Mat1: '%s' Mat2: '%s' Speed %f particle system '%s' pos: %s\n",
|
||||
// GetName().c_str(),
|
||||
// apSecondSurface->GetName().c_str(),
|
||||
// afSpeed,sPS.c_str(),
|
||||
// mtxPos.GetTranslation().ToString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::UpdateRollEffect(iPhysicsBody *apBody) {
|
||||
if (msRollSoundName == "" || mRollAxisFlags == 0)
|
||||
return;
|
||||
|
||||
/////////////////////////////////
|
||||
// Get the max angular speed
|
||||
cVector3f vAngularSpeed = cMath::MatrixMul(apBody->GetLocalMatrix().GetRotation(),
|
||||
apBody->GetAngularVelocity());
|
||||
float fRollingSpeed = 0;
|
||||
// X
|
||||
if (mRollAxisFlags & eRollAxisFlag_X)
|
||||
fRollingSpeed = ABS(vAngularSpeed.x);
|
||||
// Y
|
||||
if (mRollAxisFlags & eRollAxisFlag_Y)
|
||||
if (fRollingSpeed < ABS(vAngularSpeed.y))
|
||||
fRollingSpeed = ABS(vAngularSpeed.y);
|
||||
// Z
|
||||
if (mRollAxisFlags & eRollAxisFlag_Z)
|
||||
if (fRollingSpeed < ABS(vAngularSpeed.z))
|
||||
fRollingSpeed = ABS(vAngularSpeed.z);
|
||||
|
||||
// Log("Rollspeed: %f\n",fRollingSpeed);
|
||||
|
||||
if (fRollingSpeed == 0 && apBody->GetRollSoundEntity() == NULL)
|
||||
return;
|
||||
|
||||
/////////////////////////////////
|
||||
// Update roll sound
|
||||
cWorld3D *pWorld = mpPhysics->GetGameWorld();
|
||||
if (pWorld == NULL)
|
||||
return;
|
||||
|
||||
cSoundHandler *pSoundHandler = pWorld->GetSound()->GetSoundHandler();
|
||||
if (pSoundHandler->GetSilent())
|
||||
return;
|
||||
|
||||
// Check if sound exist in world.
|
||||
if (pWorld->SoundEntityExists(apBody->GetRollSoundEntity()) == false) {
|
||||
apBody->SetRollSoundEntity(NULL);
|
||||
}
|
||||
|
||||
// If the body all ready has a Roll sound
|
||||
if (apBody->GetRollSoundEntity() != NULL) {
|
||||
// check if the sound should be stopped
|
||||
float fMin = cMath::Max(mfMinRollSpeed - 0.7f, 0.02f);
|
||||
if (fRollingSpeed < fMin ||
|
||||
apBody->HasCollision() == false) {
|
||||
apBody->GetRollSoundEntity()->FadeOut(4.3f);
|
||||
apBody->SetRollSoundEntity(NULL);
|
||||
// Log("Stopped Roll '%s' on body '%s'\n",msRollSoundName.c_str(),
|
||||
// apBody->GetName().c_str());
|
||||
} else {
|
||||
// Change frequency according to speed.
|
||||
float fAbsSpeed = fRollingSpeed;
|
||||
float fFreq = 1;
|
||||
float fVolume = 1;
|
||||
|
||||
// Higher than middle
|
||||
if (fAbsSpeed >= mfMiddleRollSpeed) {
|
||||
if (fAbsSpeed >= mfMaxRollFreqSpeed) {
|
||||
fFreq = mfMaxRollFreq;
|
||||
fVolume = mfMaxRollVolume;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (fAbsSpeed - mfMiddleRollSpeed) /
|
||||
(mfMaxRollFreqSpeed - mfMiddleRollSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMaxRollFreq;
|
||||
fVolume = (1 - fT) + fT * mfMaxRollVolume;
|
||||
}
|
||||
}
|
||||
// Below middle
|
||||
else {
|
||||
if (fAbsSpeed <= mfMinRollFreqSpeed) {
|
||||
fFreq = mfMinRollFreq;
|
||||
fVolume = mfMinRollVolume;
|
||||
} else {
|
||||
// Calculate how close the speed is to max.
|
||||
float fT = (mfMiddleRollSpeed - fAbsSpeed) /
|
||||
(mfMiddleRollSpeed - mfMinRollFreqSpeed);
|
||||
|
||||
fFreq = (1 - fT) + fT * mfMinRollFreq;
|
||||
fVolume = (1 - fT) + fT * mfMinRollVolume;
|
||||
}
|
||||
}
|
||||
|
||||
// Log("Speed: %f Freq: %f\n",fAbsSpeed,fFreq);
|
||||
cSoundEntity *pSound = apBody->GetRollSoundEntity();
|
||||
cSoundEntry *pEntry = pSound->GetSoundEntry(eSoundEntityType_Main);
|
||||
if (pEntry) {
|
||||
pEntry->mfNormalSpeed = fFreq;
|
||||
|
||||
// pEntry->mfNormalVolume = cMath::Max(fVolume * pSound->GetVolume(),1.0f);
|
||||
pEntry->mfNormalVolumeFadeDest = cMath::Min(fVolume * pSound->GetVolume(), 1.0f);
|
||||
pEntry->mfNormalVolumeFadeSpeed = 4.0f;
|
||||
|
||||
apBody->GetRollSoundEntity()->SetPosition(apBody->GetWorldPosition());
|
||||
|
||||
// Log("Updated Roll on body '%s' w speed %f to f: %f v: %f\n",apBody->GetName().c_str(),
|
||||
// fRollingSpeed,fFreq,fVolume);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mfMinRollSpeed <= fRollingSpeed && apBody->HasCollision()) {
|
||||
cSoundEntity *pEntity = pWorld->CreateSoundEntity("Roll",
|
||||
msRollSoundName, true);
|
||||
if (pEntity) {
|
||||
pEntity->FadeIn(3.3f);
|
||||
pEntity->SetPosition(apBody->GetWorldPosition());
|
||||
|
||||
pEntity->SetIsSaved(false);
|
||||
|
||||
apBody->SetRollSoundEntity(pEntity);
|
||||
|
||||
// Log("Starting Roll '%s' on body '%s'\n",msRollSoundName.c_str(),
|
||||
// apBody->GetName().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetElasticity(float afElasticity) {
|
||||
mfElasticity = afElasticity;
|
||||
}
|
||||
|
||||
float cSurfaceData::GetElasticity() const {
|
||||
return mfElasticity;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetStaticFriction(float afElasticity) {
|
||||
mfStaticFriction = afElasticity;
|
||||
}
|
||||
|
||||
float cSurfaceData::GetStaticFriction() const {
|
||||
return mfStaticFriction;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetKineticFriction(float afElasticity) {
|
||||
mfKineticFriction = afElasticity;
|
||||
}
|
||||
|
||||
float cSurfaceData::GetKineticFriction() const {
|
||||
return mfKineticFriction;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetPriority(int alPriority) {
|
||||
mlPriority = alPriority;
|
||||
}
|
||||
|
||||
int cSurfaceData::GetPriority() const {
|
||||
return mlPriority;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetFrictionCombMode(ePhysicsMaterialCombMode aMode) {
|
||||
mFrictionMode = aMode;
|
||||
}
|
||||
|
||||
ePhysicsMaterialCombMode cSurfaceData::GetFrictionCombMode() const {
|
||||
return mFrictionMode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::SetElasticityCombMode(ePhysicsMaterialCombMode aMode) {
|
||||
mElasticityMode = aMode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
ePhysicsMaterialCombMode cSurfaceData::GetElasticityCombMode() const {
|
||||
return mElasticityMode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void cSurfaceData::PreloadData() {
|
||||
if (msRollSoundName != "")
|
||||
mpResources->GetSoundEntityManager()->Preload(msRollSoundName);
|
||||
if (msScrapeSoundName != "")
|
||||
mpResources->GetSoundEntityManager()->Preload(msScrapeSoundName);
|
||||
|
||||
for (size_t i = 0; i < mvImpactData.size(); ++i) {
|
||||
if (mvImpactData[i]->msSoundName != "") {
|
||||
mpResources->GetSoundEntityManager()->Preload(mvImpactData[i]->msSoundName);
|
||||
}
|
||||
if (mvImpactData[i]->msPSName != "") {
|
||||
mpResources->GetParticleManager()->Preload(mvImpactData[i]->msPSName);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < mvHitData.size(); ++i) {
|
||||
if (mvHitData[i]->msSoundName != "")
|
||||
mpResources->GetSoundEntityManager()->Preload(mvHitData[i]->msSoundName);
|
||||
if (mvHitData[i]->msPSName != "")
|
||||
mpResources->GetParticleManager()->Preload(mvHitData[i]->msPSName);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
iPhysicsMaterial *cSurfaceData::ToMaterial(iPhysicsWorld *apWorld) {
|
||||
iPhysicsMaterial *pMat = NULL;
|
||||
|
||||
pMat = apWorld->GetMaterialFromName(msName);
|
||||
|
||||
if (pMat == NULL) {
|
||||
pMat = apWorld->CreateMaterial(msName);
|
||||
}
|
||||
|
||||
pMat->SetElasticity(mfElasticity);
|
||||
pMat->SetKineticFriction(mfKineticFriction);
|
||||
pMat->SetStaticFriction(mfStaticFriction);
|
||||
|
||||
pMat->SetElasticityCombMode(mElasticityMode);
|
||||
pMat->SetFrictionCombMode(mFrictionMode);
|
||||
|
||||
pMat->SetSurfaceData(this);
|
||||
|
||||
return pMat;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::CreateImpactData(float afMinSpeed) {
|
||||
cSurfaceImpactData *pData = hplNew(cSurfaceImpactData, ());
|
||||
pData->mfMinSpeed = afMinSpeed;
|
||||
|
||||
mvImpactData.push_back(pData);
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::GetImpactData(int alIdx) {
|
||||
return mvImpactData[alIdx];
|
||||
}
|
||||
|
||||
int cSurfaceData::GetImpactDataNum() {
|
||||
return (int)mvImpactData.size();
|
||||
}
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::GetImpactDataFromSpeed(float afSpeed) {
|
||||
for (size_t i = 0; i < mvImpactData.size(); ++i) {
|
||||
if (afSpeed >= mvImpactData[i]->GetMinSpeed()) {
|
||||
return mvImpactData[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::CreateHitData(float afMinSpeed) {
|
||||
cSurfaceImpactData *pData = hplNew(cSurfaceImpactData, ());
|
||||
pData->mfMinSpeed = afMinSpeed;
|
||||
|
||||
mvHitData.push_back(pData);
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::GetHitData(int alIdx) {
|
||||
return mvHitData[alIdx];
|
||||
}
|
||||
|
||||
int cSurfaceData::GetHitDataNum() {
|
||||
return (int)mvHitData.size();
|
||||
}
|
||||
|
||||
cSurfaceImpactData *cSurfaceData::GetHitDataFromSpeed(float afSpeed) {
|
||||
for (size_t i = 0; i < mvHitData.size(); ++i) {
|
||||
if (afSpeed >= mvHitData[i]->GetMinSpeed()) {
|
||||
return mvHitData[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
} // namespace hpl
|
||||
202
engines/hpl1/engine/physics/SurfaceData.h
Normal file
202
engines/hpl1/engine/physics/SurfaceData.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2010 - Frictional Games
|
||||
*
|
||||
* This file is part of HPL1 Engine.
|
||||
*/
|
||||
|
||||
#ifndef HPL_SURFACE_DATA_H
|
||||
#define HPL_SURFACE_DATA_H
|
||||
|
||||
#include "hpl1/engine/math/MathTypes.h"
|
||||
#include "hpl1/engine/physics/PhysicsMaterial.h"
|
||||
|
||||
namespace hpl {
|
||||
|
||||
#define eRollAxisFlag_X 1
|
||||
#define eRollAxisFlag_Y 2
|
||||
#define eRollAxisFlag_Z 4
|
||||
|
||||
class cPhysics;
|
||||
class iPhysicsWorld;
|
||||
class iPhysicsBody;
|
||||
class cResources;
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
class cSurfaceImpactData {
|
||||
friend class cSurfaceData;
|
||||
|
||||
public:
|
||||
float GetMinSpeed() { return mfMinSpeed; }
|
||||
|
||||
const tString &GetSoundName() { return msSoundName; }
|
||||
void SetSoundName(const tString &asName) { msSoundName = asName; }
|
||||
|
||||
const tString &GetPSName() { return msPSName; }
|
||||
void SetPSName(const tString &asName) { msPSName = asName; }
|
||||
|
||||
int GetPSPrio() { return mlPSPrio; }
|
||||
void SetPSPrio(int alPrio) { mlPSPrio = alPrio; }
|
||||
|
||||
private:
|
||||
float mfMinSpeed;
|
||||
tString msSoundName;
|
||||
tString msPSName;
|
||||
int mlPSPrio;
|
||||
};
|
||||
|
||||
typedef Common::Array<cSurfaceImpactData *> tSurfaceImpactDataVec;
|
||||
typedef tSurfaceImpactDataVec::iterator tSurfaceImpactDataVecIt;
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
class cSurfaceData {
|
||||
public:
|
||||
cSurfaceData(const tString &asName, cPhysics *apPhysics, cResources *apResources);
|
||||
~cSurfaceData();
|
||||
|
||||
const tString &GetName() const { return msName; }
|
||||
|
||||
void OnImpact(float afSpeed, const cVector3f &avPos, int alContacts, iPhysicsBody *apBody);
|
||||
void OnSlide(float afSpeed, const cVector3f &avPos, int alContacts, iPhysicsBody *apBody,
|
||||
iPhysicsBody *apSlideAgainstBody);
|
||||
void CreateImpactEffect(float afSpeed, const cVector3f &avPos, int alContacts,
|
||||
cSurfaceData *apSecondSurface);
|
||||
|
||||
void UpdateRollEffect(iPhysicsBody *apBody);
|
||||
|
||||
void SetElasticity(float afElasticity);
|
||||
float GetElasticity() const;
|
||||
void SetStaticFriction(float afElasticity);
|
||||
float GetStaticFriction() const;
|
||||
void SetKineticFriction(float afElasticity);
|
||||
float GetKineticFriction() const;
|
||||
|
||||
void SetPriority(int alPriority);
|
||||
int GetPriority() const;
|
||||
|
||||
void SetFrictionCombMode(ePhysicsMaterialCombMode aMode);
|
||||
ePhysicsMaterialCombMode GetFrictionCombMode() const;
|
||||
void SetElasticityCombMode(ePhysicsMaterialCombMode aMode);
|
||||
ePhysicsMaterialCombMode GetElasticityCombMode() const;
|
||||
|
||||
const tString &GetStepType() { return msStepType; }
|
||||
void GetStepType(const tString &asX) { msStepType = asX; }
|
||||
|
||||
void SetMinScrapeSpeed(float afX) { mfMinScrapeSpeed = afX; }
|
||||
void SetMinScrapeFreq(float afX) { mfMinScrapeFreq = afX; }
|
||||
void SetMinScrapeFreqSpeed(float afX) { mfMinScrapeFreqSpeed = afX; }
|
||||
void SetMaxScrapeFreq(float afX) { mfMaxScrapeFreq = afX; }
|
||||
void SetMaxScrapeFreqSpeed(float afX) { mfMaxScrapeFreqSpeed = afX; }
|
||||
void SetMiddleScrapeSpeed(float afX) { mfMiddleScrapeSpeed = afX; }
|
||||
void SetMinScrapeContacts(int alX) { mlMinScrapeContacts = alX; }
|
||||
void SetScrapeSoundName(const tString &asName) { msScrapeSoundName = asName; }
|
||||
|
||||
void SetMinRollSpeed(float afX) { mfMinRollSpeed = afX; }
|
||||
void SetMinRollFreq(float afX) { mfMinRollFreq = afX; }
|
||||
void SetMinRollVolume(float afX) { mfMinRollVolume = afX; }
|
||||
void SetMinRollFreqSpeed(float afX) { mfMinRollFreqSpeed = afX; }
|
||||
void SetMaxRollFreq(float afX) { mfMaxRollFreq = afX; }
|
||||
void SetMaxRollVolume(float afX) { mfMaxRollVolume = afX; }
|
||||
void SetMaxRollFreqSpeed(float afX) { mfMaxRollFreqSpeed = afX; }
|
||||
void SetMiddleRollSpeed(float afX) { mfMiddleRollSpeed = afX; }
|
||||
void SetRollSoundName(const tString &asName) { msRollSoundName = asName; }
|
||||
void SetRollAxisFlags(tFlag aAxisFlags) { mRollAxisFlags = aAxisFlags; }
|
||||
|
||||
void PreloadData();
|
||||
|
||||
iPhysicsMaterial *ToMaterial(iPhysicsWorld *apWorld);
|
||||
|
||||
/**
|
||||
* This must be added with the largest speed first.
|
||||
**/
|
||||
cSurfaceImpactData *CreateImpactData(float afMinSpeed);
|
||||
cSurfaceImpactData *GetImpactData(int alIdx);
|
||||
int GetImpactDataNum();
|
||||
/**
|
||||
* Gets the the appropriate impact data depending on speed. It gets the data with highest speed not higher than afSpeed
|
||||
* \param afSpeed The speed value.
|
||||
* \return
|
||||
*/
|
||||
cSurfaceImpactData *GetImpactDataFromSpeed(float afSpeed);
|
||||
|
||||
/**
|
||||
* This must be added with the largest speed first.
|
||||
**/
|
||||
cSurfaceImpactData *CreateHitData(float afMinSpeed);
|
||||
cSurfaceImpactData *GetHitData(int alIdx);
|
||||
int GetHitDataNum();
|
||||
/**
|
||||
* Gets the the appropriate hit data depending on speed. It gets the data with highest speed not higher than afSpeed
|
||||
* \param afSpeed The speed value.
|
||||
* \return
|
||||
*/
|
||||
cSurfaceImpactData *GetHitDataFromSpeed(float afSpeed);
|
||||
|
||||
protected:
|
||||
cResources *mpResources;
|
||||
cPhysics *mpPhysics;
|
||||
tString msName;
|
||||
|
||||
// Properties
|
||||
ePhysicsMaterialCombMode mFrictionMode;
|
||||
ePhysicsMaterialCombMode mElasticityMode;
|
||||
|
||||
float mfElasticity;
|
||||
float mfStaticFriction;
|
||||
float mfKineticFriction;
|
||||
|
||||
int mlPriority;
|
||||
|
||||
float mfMinScrapeSpeed;
|
||||
float mfMinScrapeFreq;
|
||||
float mfMinScrapeFreqSpeed;
|
||||
float mfMaxScrapeFreq;
|
||||
float mfMaxScrapeFreqSpeed;
|
||||
float mfMiddleScrapeSpeed;
|
||||
int mlMinScrapeContacts;
|
||||
tString msScrapeSoundName;
|
||||
|
||||
float mfMinRollSpeed;
|
||||
float mfMinRollFreq;
|
||||
float mfMinRollVolume;
|
||||
float mfMinRollFreqSpeed;
|
||||
float mfMaxRollFreq;
|
||||
float mfMaxRollVolume;
|
||||
float mfMaxRollFreqSpeed;
|
||||
float mfMiddleRollSpeed;
|
||||
int mlMinRollContacts;
|
||||
tString msRollSoundName;
|
||||
tFlag mRollAxisFlags;
|
||||
|
||||
tString msStepType;
|
||||
|
||||
tSurfaceImpactDataVec mvImpactData;
|
||||
|
||||
tSurfaceImpactDataVec mvHitData;
|
||||
};
|
||||
|
||||
} // namespace hpl
|
||||
|
||||
#endif // HPL_SURFACE_DATA_H
|
||||
Reference in New Issue
Block a user