Files
FC1/CryPhysics/physicalentity.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

621 lines
21 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Physical Entity
//
// File: physicalentity.cpp
// Description : PhysicalEntity class implementation
//
// History:
// -:Created by Anton Knyazev
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "bvtree.h"
#include "geometry.h"
#include "rigidbody.h"
#include "physicalplaceholder.h"
#include "physicalentity.h"
#include "geoman.h"
#include "physicalworld.h"
RigidBody g_StaticRigidBody;
CPhysicalEntity g_StaticPhysicalEntity(0);
CPhysicalEntity::CPhysicalEntity(CPhysicalWorld *pworld)
{
m_pos.zero(); m_qrot.SetIdentity();
m_BBox[0].zero(); m_BBox[1].zero();
m_iSimClass = 0; m_iPrevSimClass = -1;
m_nGridThunks = m_nGridThunksAlloc = 0;
m_pGridThunks = 0;
m_ig[0].x=m_ig[1].x=m_ig[0].y=m_ig[1].y = -2;
m_prev = m_next = 0; m_bProcessed = 0;
m_nRefCount = 0;//1; 0 means that initially no other physical entity references this one
m_nParts = 0;
m_nPartsAlloc = 1;
m_parts = &m_defpart;
m_iLastIdx = 0;
m_pWorld = pworld;
m_pOuterEntity = 0;
m_pBoundingGeometry = 0;
m_bProcessed_aux = 0;
m_nColliders = m_nCollidersAlloc = 0;
m_pColliders = 0;
m_iGroup = -1;
m_bMoved = 0;
m_id = -1;
m_pForeignData = 0;
m_iForeignData = m_iForeignFlags = 0;
m_timeIdle = m_maxTimeIdle = 0;
m_bPermanent = 1;
m_pEntBuddy = 0;
m_flags = pef_pushable_by_players|pef_traceable;
}
CPhysicalEntity::~CPhysicalEntity()
{
for(int i=0;i<m_nParts;i++) if (m_parts[i].pPhysGeom) {
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeom);
if (m_parts[i].pPhysGeomProxy!=m_parts[i].pPhysGeom)
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeomProxy);
}
if (m_pGridThunks) delete[] m_pGridThunks;
if (m_parts!=&m_defpart) delete[] m_parts;
if (m_pColliders) delete[] m_pColliders;
}
void CPhysicalEntity::ComputeBBox()
{
if (m_nParts==0)
m_BBox[0]=m_BBox[1]=m_pos;
else {
IGeometry *pGeom[3];
matrix3x3f R;
int i,j; box abox; vectorf sz,pos;
m_BBox[0]=vectorf(MAX); m_BBox[1]=vectorf(MIN);
for(i=0;i<m_nParts;i++) {
pGeom[0] = m_parts[i].pPhysGeomProxy->pGeom;
pGeom[1]=pGeom[2] = m_parts[i].pPhysGeom->pGeom;
j=0; do {
pGeom[j]->GetBBox(&abox);
//(m_qrot*m_parts[i].q).getmatrix(R); //Q2M_IVO
R = matrix3x3f(m_qrot*m_parts[i].q);
abox.Basis *= R.T();
sz = (abox.size*abox.Basis.Fabs())*m_parts[i].scale;
pos = m_pos+m_qrot*(m_parts[i].pos+m_parts[i].q*abox.center*m_parts[i].scale);
m_parts[i].BBox[0] = pos-sz;
m_parts[i].BBox[1] = pos+sz;
m_BBox[0].x = min_safe(m_BBox[0].x, m_parts[i].BBox[0].x);
m_BBox[0].y = min_safe(m_BBox[0].y, m_parts[i].BBox[0].y);
m_BBox[0].z = min_safe(m_BBox[0].z, m_parts[i].BBox[0].z);
m_BBox[1].x = max_safe(m_BBox[1].x, m_parts[i].BBox[1].x);
m_BBox[1].y = max_safe(m_BBox[1].y, m_parts[i].BBox[1].y);
m_BBox[1].z = max_safe(m_BBox[1].z, m_parts[i].BBox[1].z);
j++;
} while(pGeom[j]!=pGeom[j-1]);
}
}
if (m_pEntBuddy) {
m_pEntBuddy->m_BBox[0] = m_BBox[0];
m_pEntBuddy->m_BBox[1] = m_BBox[1];
}
}
int CPhysicalEntity::SetParams(pe_params *_params)
{
if (_params->type==pe_params_pos::type_id) {
pe_params_pos *params = (pe_params_pos*)_params;
get_xqs_from_matrices(params->pMtx3x3,params->pMtx3x3T,params->pMtx4x4,params->pMtx4x4T, params->pos,params->q,params->scale);
ENTITY_VALIDATE("CPhysicalEntity:SetParams(pe_params_pos)",params);
int bPosChanged = 0;
if (!is_unused(params->pos)) { m_pos = params->pos; bPosChanged=1; }
if (!is_unused(params->q)) { m_qrot = params->q; bPosChanged=1; }
if (!is_unused(params->iSimClass) && m_iSimClass>=0 && m_iSimClass<7) {
m_iSimClass = params->iSimClass;
m_pWorld->RepositionEntity(this,2);
}
if (!is_unused(params->scale)) {
for(int i=0;i<m_nParts;i++) {
m_parts[i].pos *= params->scale/m_parts[i].scale;
m_parts[i].scale = params->scale;
} bPosChanged=1;
}
if (params->bRecalcBounds && bPosChanged) {
CPhysicalEntity **pentlist;
// make triggers aware of the object's movements
if (!(m_flags & pef_never_affect_triggers))
m_pWorld->GetEntitiesAround(m_BBox[0],m_BBox[1],pentlist,ent_triggers,this);
ComputeBBox();
m_pWorld->RepositionEntity(this);
if (!(m_flags & pef_never_affect_triggers))
m_pWorld->GetEntitiesAround(m_BBox[0],m_BBox[1],pentlist,ent_triggers,this);
}
return 1;
}
if (_params->type==pe_params_bbox::type_id) {
pe_params_bbox *params = (pe_params_bbox*)_params;
ENTITY_VALIDATE("CPhysicalEntity::SetParams(pe_params_bbox)",params);
if (!is_unused(params->BBox[0])) m_BBox[0] = params->BBox[0];
if (!is_unused(params->BBox[1])) m_BBox[1] = params->BBox[1];
if (m_pEntBuddy) {
m_pEntBuddy->m_BBox[0] = m_BBox[0];
m_pEntBuddy->m_BBox[1] = m_BBox[1];
}
m_pWorld->RepositionEntity(this,1);
return 1;
}
if (_params->type==pe_params_part::type_id) {
pe_params_part *params = (pe_params_part*)_params;
int i = params->ipart;
if (i<0)
for(i=0;i<m_nParts && m_parts[i].id!=params->partid;i++);
if (i>=m_nParts)
return 0;
get_xqs_from_matrices(params->pMtx3x3,params->pMtx3x3T,params->pMtx4x4,params->pMtx4x4T, params->pos,params->q,params->scale);
ENTITY_VALIDATE("CPhysicalEntity:SetParams(pe_params_part)",params);
if (!is_unused(params->pos.x)) m_parts[i].pos = params->pos;
if (!is_unused(params->q)) m_parts[i].q = params->q;
if (!is_unused(params->scale)) m_parts[i].scale = params->scale;
if (!is_unused(params->mass)) m_parts[i].mass = params->mass;
if (!is_unused(params->density)) m_parts[i].mass = m_parts[i].pPhysGeom->V*cube(m_parts[i].scale)*params->density;
if (!is_unused(params->pPhysGeom) && params->pPhysGeom!=m_parts[i].pPhysGeom) {
if (m_parts[i].pPhysGeom==m_parts[i].pPhysGeomProxy)
m_parts[i].pPhysGeomProxy = params->pPhysGeom;
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeom);
m_parts[i].pPhysGeom = params->pPhysGeom;
m_pWorld->GetGeomManager()->AddRefGeometry(params->pPhysGeom);
}
if (!is_unused(params->pPhysGeomProxy) && params->pPhysGeomProxy!=m_parts[i].pPhysGeomProxy) {
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeomProxy);
m_parts[i].pPhysGeomProxy = params->pPhysGeomProxy;
m_pWorld->GetGeomManager()->AddRefGeometry(params->pPhysGeomProxy);
}
m_parts[i].flags = m_parts[i].flags & params->flagsAND | params->flagsOR;
m_parts[i].flagsCollider = m_parts[i].flagsCollider & params->flagsColliderAND | params->flagsColliderOR;
if (params->bRecalcBBox)
ComputeBBox();
return i+1;
}
if (_params->type==pe_params_outer_entity::type_id) {
m_pOuterEntity = (CPhysicalEntity*)((pe_params_outer_entity*)_params)->pOuterEntity;
m_pBoundingGeometry = (CGeometry*)((pe_params_outer_entity*)_params)->pBoundingGeometry;
return 1;
}
if (_params->type==pe_params_foreign_data::type_id) {
pe_params_foreign_data *params = (pe_params_foreign_data*)_params;
if (!is_unused(params->iForeignData)) m_iForeignData = params->iForeignData;
if (!is_unused(params->pForeignData)) m_pForeignData = params->pForeignData;
if (!is_unused(params->iForeignFlags)) m_iForeignFlags = params->iForeignFlags;
if (m_pEntBuddy) {
m_pEntBuddy->m_pForeignData = m_pForeignData;
m_pEntBuddy->m_iForeignData = m_iForeignData;
m_pEntBuddy->m_iForeignFlags = m_iForeignFlags;
}
return 1;
}
if (_params->type==pe_params_flags::type_id) {
pe_params_flags *params = (pe_params_flags*)_params;
int flags = m_flags;
if (!is_unused(params->flags)) m_flags = params->flags;
if (!is_unused(params->flagsAND)) m_flags &= params->flagsAND;
if (!is_unused(params->flagsOR)) m_flags |= params->flagsOR;
if (m_flags&pef_traceable && m_ig[0].x==-3) {
m_ig[0].x=m_ig[1].x=m_ig[0].y=m_ig[1].y = -2;
if (m_pos.len2()>0)
m_pWorld->RepositionEntity(this,1);
}
if (!(m_flags&pef_traceable) && m_ig[0].x!=-3) {
m_pWorld->DetachEntityGridThunks(this);
m_ig[0].x=m_ig[1].x=m_ig[0].y=m_ig[1].y = -3;
}
return 1;
}
return 0;
}
int CPhysicalEntity::GetParams(pe_params *_params)
{
if (_params->type==pe_params_bbox::type_id) {
pe_params_bbox *params = (pe_params_bbox*)_params;
params->BBox[0] = m_BBox[0];
params->BBox[1] = m_BBox[1];
return 1;
}
if (_params->type==pe_params_outer_entity::type_id) {
((pe_params_outer_entity*)_params)->pOuterEntity = m_pOuterEntity;
((pe_params_outer_entity*)_params)->pBoundingGeometry = m_pBoundingGeometry;
return 1;
}
if (_params->type==pe_params_foreign_data::type_id) {
pe_params_foreign_data *params = (pe_params_foreign_data*)_params;
params->iForeignData = m_iForeignData;
params->pForeignData = m_pForeignData;
params->iForeignFlags = m_iForeignFlags;
return 1;
}
if (_params->type==pe_params_part::type_id) {
pe_params_part *params = (pe_params_part*)_params;
int i;
if (params->ipart==-1 && params->partid>=0) {
for(i=0;i<m_nParts && m_parts[i].id!=params->partid;i++);
if (i==m_nParts) return 0;
} else
i = params->ipart;
params->partid = m_parts[params->ipart = i].id;
params->pos = m_parts[i].pos;
params->q = m_parts[i].q;
params->scale = m_parts[i].scale;
if (params->pMtx3x3) //resq.getmatrix((matrix3x3f&)*status->pMtx3x3) *= resscale; //Q2M_IVO
(matrix3x3f&)*params->pMtx3x3 = (matrix3x3f(m_parts[i].q)*m_parts[i].scale);
if (params->pMtx3x3T) //resq.getmatrix((matrix3x3Tf&)*params->pMtx3x3T) *= resscale; //Q2M_IVO
(matrix3x3Tf&)*params->pMtx3x3T=(matrix3x3f(m_parts[i].q)*m_parts[i].scale);
if (params->pMtx4x4) //(resq.getmatrix((matrix3x3in4x4f&)*params->pMtx4x4)*=resscale).SetColumn(3,respos); //Q2M_IVO
((matrix3x3in4x4f&)*params->pMtx4x4 = (matrix3x3f(m_parts[i].q)*m_parts[i].scale)).SetColumn(3,m_parts[i].pos);
if (params->pMtx4x4T) //(resq.getmatrix((matrix3x3in4x4Tf&)*params->pMtx4x4T)*=resscale).SetColumn(3,respos); //Q2M_IVO
((matrix3x3in4x4Tf&)*params->pMtx4x4T = (matrix3x3f(m_parts[i].q)*m_parts[i].scale)).SetColumn(3,m_parts[i].pos);
params->flagsOR=params->flagsAND = m_parts[i].flags;
params->flagsColliderOR=params->flagsColliderAND = m_parts[i].flagsCollider;
params->mass = m_parts[i].mass;
params->density = m_parts[i].pPhysGeomProxy->V>0 ?
m_parts[i].mass/(m_parts[i].pPhysGeomProxy->V*cube(m_parts[i].scale)) : 0;
params->pPhysGeom = m_parts[i].pPhysGeom;
params->pPhysGeomProxy = m_parts[i].pPhysGeomProxy;
}
if (_params->type==pe_params_flags::type_id) {
((pe_params_flags*)_params)->flags = m_flags;
return 1;
}
return 0;
}
int CPhysicalEntity::GetStatus(pe_status *_status)
{
if (_status->type==pe_status_pos::type_id) {
pe_status_pos *status = (pe_status_pos*)_status;
vectorf respos;
quaternionf resq;
float resscale;
int i;
if (status->ipart==-1 && status->partid>=0) {
for(i=0;i<m_nParts && m_parts[i].id!=status->partid;i++);
if (i==m_nParts) return 0;
} else
i = status->ipart;
if (i==-1) {
respos=m_pos; resq=m_qrot; resscale=1.0f;
for(i=0,status->flagsOR=0,status->flagsAND=-1;i<m_nParts;i++)
status->flagsOR|=m_parts[i].flags, status->flagsAND&=m_parts[i].flags;
if (m_nParts>0) {
status->pGeom = m_parts[0].pPhysGeom->pGeom;
status->pGeomProxy = m_parts[0].pPhysGeomProxy->pGeom;
} else
status->pGeom = status->pGeomProxy = 0;
} else {
if (status->flags & status_local) {
respos = m_parts[i].pos; resq = m_parts[i].q;
} else {
respos = m_pos+m_qrot*m_parts[i].pos;
resq = m_qrot*m_parts[i].q;
}
resscale = m_parts[i].scale;
status->flagsOR = status->flagsAND = m_parts[i].flags;
status->pGeom = m_parts[i].pPhysGeom->pGeom;
status->pGeomProxy = m_parts[i].pPhysGeomProxy->pGeom;
}
status->pos = respos;
status->q = resq;
status->scale = resscale;
status->iSimClass = m_iSimClass;
if (status->pMtx3x3) //resq.getmatrix((matrix3x3f&)*status->pMtx3x3) *= resscale; //Q2M_IVO
(matrix3x3f&)*status->pMtx3x3 = (matrix3x3f(resq)*resscale);
if (status->pMtx3x3T) //resq.getmatrix((matrix3x3Tf&)*status->pMtx3x3T) *= resscale; //Q2M_IVO
(matrix3x3Tf&)*status->pMtx3x3T=(matrix3x3f(resq)*resscale);
if (status->pMtx4x4) //(resq.getmatrix((matrix3x3in4x4f&)*status->pMtx4x4)*=resscale).SetColumn(3,respos); //Q2M_IVO
((matrix3x3in4x4f&)*status->pMtx4x4 = (matrix3x3f(resq)*resscale)).SetColumn(3,respos);
if (status->pMtx4x4T) //(resq.getmatrix((matrix3x3in4x4Tf&)*status->pMtx4x4T)*=resscale).SetColumn(3,respos); //Q2M_IVO
((matrix3x3in4x4Tf&)*status->pMtx4x4T = (matrix3x3f(resq)*resscale)).SetColumn(3,respos);
status->BBox[0] = m_BBox[0]-m_pos;
status->BBox[1] = m_BBox[1]-m_pos;
return 1;
}
if (_status->type==pe_status_id::type_id) {
pe_status_id *status = (pe_status_id*)_status;
int ipart = status->ipart;
if (ipart<0)
for(ipart=0;ipart<m_nParts-1 && m_parts[ipart].id!=status->partid;ipart++);
if (ipart>=m_nParts)
return 0;
phys_geometry *pgeom = status->bUseProxy ? m_parts[ipart].pPhysGeomProxy : m_parts[ipart].pPhysGeom;
if ((unsigned int)status->iPrim >= (unsigned int)pgeom->pGeom->GetPrimitiveCount() ||
pgeom->pGeom->GetType()==GEOM_TRIMESH && status->iFeature>2)
return 0;
status->id = pgeom->pGeom->GetPrimitiveId(status->iPrim, status->iFeature);
status->id = status->id&~(status->id>>31) | m_parts[ipart].surface_idx&status->id>>31;
return 1;
}
if (_status->type==pe_status_nparts::type_id)
return m_nParts;
if (_status->type==pe_status_awake::type_id)
return IsAwake();
if (_status->type==pe_status_contains_point::type_id)
return IsPointInside(((pe_status_contains_point*)_status)->pt);
if (_status->type==pe_status_caps::type_id) {
pe_status_caps *status = (pe_status_caps*)_status;
status->bCanAlterOrientation = 0;
return 1;
}
return 0;
};
int CPhysicalEntity::Action(pe_action *_action)
{
if (_action->type==pe_action_awake::type_id && m_iSimClass>=0 && m_iSimClass<7) {
Awake(((pe_action_awake*)_action)->bAwake,1);
return 1;
}
if (_action->type==pe_action_remove_all_parts::type_id) {
for(int i=m_nParts-1;i>=0;i--)
RemoveGeometry(m_parts[i].id);
return 1;
}
return 0;
}
int CPhysicalEntity::AddGeometry(phys_geometry *pgeom, pe_geomparams* params, int id)
{
if (!pgeom)
return -1;
box abox; pgeom->pGeom->GetBBox(&abox);
float mindim=min(min(abox.size.x,abox.size.y),abox.size.z), mindims=mindim*params->scale;
float maxdim=max(max(abox.size.x,abox.size.y),abox.size.z), maxdims=maxdim*params->scale;
if (id>=0) {
int i; for(i=0;i<m_nParts && m_parts[i].id!=id;i++);
if (i<m_nParts) {
if (params->flags & geom_proxy) {
if (pgeom) {
if (m_parts[i].pPhysGeomProxy!=pgeom)
m_pWorld->GetGeomManager()->AddRefGeometry(pgeom);
m_parts[i].pPhysGeomProxy = pgeom;
if (mindims<0.15f)
m_parts[i].flags |= geom_has_thin_parts;
}
} else {
m_parts[i].pos = params->pos;
m_parts[i].q = params->q;
}
return id;
}
}
get_xqs_from_matrices(params->pMtx3x3,params->pMtx3x3T,params->pMtx4x4,params->pMtx4x4T, params->pos,params->q,params->scale);
ENTITY_VALIDATE_ERRCODE("CPhysicalEntity:AddGeometry",params,-1);
if (m_nParts==m_nPartsAlloc) {
geom *pparts = m_parts;
memcpy(m_parts = new geom[m_nPartsAlloc=m_nPartsAlloc+4&~3], pparts, sizeof(geom)*m_nParts);
if (pparts!=&m_defpart) delete[] pparts;
}
m_parts[m_nParts].id = id<0 ? m_iLastIdx++:id;
m_parts[m_nParts].pPhysGeom = m_parts[m_nParts].pPhysGeomProxy = pgeom;
m_pWorld->GetGeomManager()->AddRefGeometry(pgeom);
m_parts[m_nParts].surface_idx = pgeom->surface_idx;
if (!is_unused(params->surface_idx)) m_parts[m_nParts].surface_idx = params->surface_idx;
m_parts[m_nParts].flags = params->flags & ~geom_proxy;
m_parts[m_nParts].flagsCollider = params->flagsCollider;
m_parts[m_nParts].pos = params->pos;
m_parts[m_nParts].q = params->q;
m_parts[m_nParts].scale = params->scale;
if (is_unused(params->minContactDist)) {
m_parts[m_nParts].minContactDist = max(maxdims*0.03f,mindims*(mindims<maxdims*0.3f ? 0.4f:0.1f));
if (mindims<0.15f)
m_parts[m_nParts].flags |= geom_has_thin_parts;
} else
m_parts[m_nParts].minContactDist = params->minContactDist;
m_parts[m_nParts].maxdim = maxdim;
m_nParts++;
if (params->bRecalcBBox) {
ComputeBBox();
m_pWorld->RepositionEntity(this,1);
}
return m_parts[m_nParts-1].id;
}
void CPhysicalEntity::RemoveGeometry(int id)
{
for(int i=0;i<m_nParts;i++) if (m_parts[i].id==id) {
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeom);
if (m_parts[i].pPhysGeomProxy!=m_parts[i].pPhysGeom)
m_pWorld->GetGeomManager()->UnregisterGeometry(m_parts[i].pPhysGeomProxy);
for(;i<m_nParts-1;i++) m_parts[i]=m_parts[i+1];
m_nParts--;
ComputeBBox();
m_pWorld->RepositionEntity(this,1);
return;
}
}
RigidBody *CPhysicalEntity::GetRigidBody(int ipart)
{
g_StaticRigidBody.P.zero(); g_StaticRigidBody.v.zero();
g_StaticRigidBody.L.zero(); g_StaticRigidBody.w.zero();
return &g_StaticRigidBody;
}
int CPhysicalEntity::IsPointInside(vectorf pt)
{
pt = (pt-m_pos)*m_qrot;
if (m_pBoundingGeometry)
return m_pBoundingGeometry->PointInsideStatus(pt);
for(int i=0;i<m_nParts;i++) if ((m_parts[i].flags & geom_collides) &&
m_parts[i].pPhysGeom->pGeom->PointInsideStatus((pt-m_parts[i].pos)*m_parts[i].q))
return 1;
return 0;
}
void CPhysicalEntity::AlertNeighbourhoodND()
{
int i;
if (m_iSimClass>3)
return;
for(i=0;i<m_nColliders;i++) if (m_pColliders[i]!=this) {
m_pColliders[i]->RemoveCollider(this);
m_pColliders[i]->Awake();
m_pColliders[i]->Release();
m_nRefCount--;
}
m_nColliders = 0;
if (m_nRefCount>0 || m_flags&pef_always_notify_on_deletion) {
CPhysicalEntity **pentlist;
vectorf inflator = (m_BBox[1]-m_BBox[0])*1E-3f+vectorf(4,4,4)*m_pWorld->m_vars.maxContactGap;
for(i=m_pWorld->GetEntitiesAround(m_BBox[0]-inflator,m_BBox[1]+inflator, pentlist,
ent_sleeping_rigid|ent_rigid|ent_living|ent_independent|ent_triggers)-1; i>=0; i--)
pentlist[i]->Awake();
}
}
int CPhysicalEntity::RemoveCollider(CPhysicalEntity *pCollider, bool bRemoveAlways)
{
if (m_pColliders && m_iSimClass>0) {
int i,islot; for(i=0;i<m_nColliders && m_pColliders[i]!=pCollider;i++);
if (i<m_nColliders) {
for(islot=i;i<m_nColliders-1;i++) m_pColliders[i] = m_pColliders[i+1];
if (pCollider!=this)
pCollider->Release();
m_nColliders--; return islot;
}
}
return -1;
}
int CPhysicalEntity::AddCollider(CPhysicalEntity *pCollider)
{
if (m_iSimClass==0)
return 1;
int i,j;
for(i=0;i<m_nColliders && m_pColliders[i]!=pCollider;i++);
if (i==m_nColliders) {
if (m_nColliders==m_nCollidersAlloc) {
CPhysicalEntity **pColliders = m_pColliders;
memcpy(m_pColliders = new (CPhysicalEntity*[m_nCollidersAlloc+=8]), pColliders, sizeof(CPhysicalEntity*)*m_nColliders);
if (pColliders) delete[] pColliders;
}
for(i=0;i<m_nColliders && pCollider->GetMassInv()>m_pColliders[i]->GetMassInv();i++);
for(j=m_nColliders-1; j>=i; j--) m_pColliders[j+1] = m_pColliders[j];
m_pColliders[i] = pCollider; m_nColliders++;
if (pCollider!=this)
pCollider->AddRef();
}
return i;
}
void CPhysicalEntity::DrawHelperInformation(void (*DrawLineFunc)(float*,float*), int flags)
{
if (flags & pe_helper_bbox) {
int i,j;
vectorf sz,center,pt[8];
center = (m_BBox[1]+m_BBox[0])*0.5f;
sz = (m_BBox[1]-m_BBox[0])*0.5f;
for(i=0;i<8;i++)
pt[i] = vectorf(sz.x*((i<<1&2)-1),sz.y*((i&2)-1),sz.z*((i>>1&2)-1))+center;
for(i=0;i<8;i++) for(j=0;j<3;j++) if (i&1<<j)
DrawLineFunc(pt[i],pt[i^1<<j]);
}
if (flags & pe_helper_geometry) {
int iLevel = flags>>16;
geom_world_data gwd;
for(int i=0;i<m_nParts;i++) {
//(m_qrot*m_parts[i].q).getmatrix(gwd.R); //Q2M_IVO
gwd.R = matrix3x3f(m_qrot*m_parts[i].q);
gwd.offset = m_pos + m_qrot*m_parts[i].pos;
gwd.scale = m_parts[i].scale;
m_parts[i].pPhysGeom->pGeom->DrawWireframe(DrawLineFunc,&gwd, iLevel);
if (m_parts[i].pPhysGeomProxy!=m_parts[i].pPhysGeom)
m_parts[i].pPhysGeomProxy->pGeom->DrawWireframe(DrawLineFunc,&gwd, iLevel);
}
}
}
void CPhysicalEntity::GetMemoryStatistics(ICrySizer *pSizer)
{
if (GetType()==PE_STATIC)
pSizer->AddObject(this, sizeof(CPhysicalEntity));
if (m_parts!=&m_defpart)
pSizer->AddObject(m_parts, m_nParts*sizeof(m_parts[0]));
pSizer->AddObject(m_pGridThunks, m_nGridThunksAlloc*sizeof(m_pGridThunks[0]));
pSizer->AddObject(m_pColliders, m_nCollidersAlloc*sizeof(m_pColliders[0]));
}
int CPhysicalEntity::GetStateSnapshotTxt(char *txtbuf,int szbuf, float time_back)
{
CStream stm;
GetStateSnapshot(stm,time_back);
int size=bin2ascii(stm.GetPtr(),(stm.GetSize()-1>>3)+1,(unsigned char*)txtbuf);
/*
// debugging
static char test[1024*16];
int testsize=ascii2bin((const unsigned char*)txtbuf,size,(unsigned char*)test);
if(memcmp(test,stm.GetPtr(),testsize)!=0)
{
char str[256];
sprintf(str,"%d %d\n",size,testsize);
OutputDebugString(str);
}
*/
return size;
}
void CPhysicalEntity::SetStateFromSnapshotTxt(const char *txtbuf,int szbuf)
{
CStream stm;
stm.SetSize(ascii2bin((const unsigned char*)txtbuf,szbuf,stm.GetPtr())*8);
SetStateFromSnapshot(stm);
}