summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/References.cpp77
-rw-r--r--src/core/World.cpp14
-rw-r--r--src/entities/Entity.cpp1017
-rw-r--r--src/entities/Entity.h14
-rw-r--r--src/render/Coronas.cpp236
-rw-r--r--src/render/Occlusion.cpp34
-rw-r--r--src/render/Particle.cpp40
-rw-r--r--src/render/Renderer.cpp11
-rw-r--r--src/rw/RwHelper.cpp20
9 files changed, 751 insertions, 712 deletions
diff --git a/src/core/References.cpp b/src/core/References.cpp
index 52abbc3e..dc83d96d 100644
--- a/src/core/References.cpp
+++ b/src/core/References.cpp
@@ -22,6 +22,83 @@ CReferences::Init(void)
}
void
+CEntity::RegisterReference(CEntity **pent)
+{
+ if(IsBuilding())
+ return;
+ CReference *ref;
+ // check if already registered
+ for(ref = m_pFirstReference; ref; ref = ref->next)
+ if(ref->pentity == pent)
+ return;
+ // have to allocate new reference
+ ref = CReferences::pEmptyList;
+ if(ref){
+ CReferences::pEmptyList = ref->next;
+
+ ref->pentity = pent;
+ ref->next = m_pFirstReference;
+ m_pFirstReference = ref;
+ return;
+ }
+ return;
+}
+
+// Clean up the reference from *pent -> 'this'
+void
+CEntity::CleanUpOldReference(CEntity **pent)
+{
+ CReference* ref, ** lastnextp;
+ lastnextp = &m_pFirstReference;
+ for (ref = m_pFirstReference; ref; ref = ref->next) {
+ if (ref->pentity == pent) {
+ *lastnextp = ref->next;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = ref;
+ break;
+ }
+ lastnextp = &ref->next;
+ }
+}
+
+// Clear all references to this entity
+void
+CEntity::ResolveReferences(void)
+{
+ CReference *ref;
+ // clear pointers to this entity
+ for(ref = m_pFirstReference; ref; ref = ref->next)
+ if(*ref->pentity == this)
+ *ref->pentity = nil;
+ // free list
+ if(m_pFirstReference){
+ for(ref = m_pFirstReference; ref->next; ref = ref->next)
+ ;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = m_pFirstReference;
+ m_pFirstReference = nil;
+ }
+}
+
+// Free all references that no longer point to this entity
+void
+CEntity::PruneReferences(void)
+{
+ CReference *ref, *next, **lastnextp;
+ lastnextp = &m_pFirstReference;
+ for(ref = m_pFirstReference; ref; ref = next){
+ next = ref->next;
+ if(*ref->pentity == this)
+ lastnextp = &ref->next;
+ else{
+ *lastnextp = ref->next;
+ ref->next = CReferences::pEmptyList;
+ CReferences::pEmptyList = ref;
+ }
+ }
+}
+
+void
CReferences::RemoveReferencesToPlayer(void)
{
if(FindPlayerVehicle())
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 7d5f89b8..ae4b72ec 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -1643,14 +1643,24 @@ CWorld::ExtinguishAllCarFiresInArea(CVector point, float range)
}
}
+inline void
+AddSteamsFromGround(CPtrList& list)
+{
+ CPtrNode* pNode = list.first;
+ while (pNode) {
+ ((CEntity*)pNode->item)->AddSteamsFromGround(nil);
+ pNode = pNode->next;
+ }
+}
+
void
CWorld::AddParticles(void)
{
for(int32 y = 0; y < NUMSECTORS_Y; y++) {
for(int32 x = 0; x < NUMSECTORS_X; x++) {
CSector *pSector = GetSector(x, y);
- CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]);
- CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]);
+ AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]);
+ AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]);
}
}
}
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 9db36bcf..9b6be5f6 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -4,35 +4,27 @@
#include "RwHelper.h"
#include "ModelIndices.h"
#include "Timer.h"
-#include "Placeable.h"
#include "Entity.h"
#include "Object.h"
-#include "ParticleObject.h"
-#include "Lights.h"
#include "World.h"
#include "Camera.h"
#include "Glass.h"
-#include "Clock.h"
#include "Weather.h"
#include "Timecycle.h"
-#include "Bridge.h"
#include "TrafficLights.h"
#include "Coronas.h"
#include "PointLights.h"
#include "Shadows.h"
#include "Pickups.h"
#include "SpecialFX.h"
-#include "References.h"
#include "TxdStore.h"
#include "Zones.h"
+#include "MemoryHeap.h"
#include "Bones.h"
#include "Debug.h"
-#include "Renderer.h"
#include "Ped.h"
#include "Dummy.h"
#include "WindModifiers.h"
-#include "Occlusion.h"
-#include "MemoryHeap.h"
//--MIAMI: file done
@@ -102,186 +94,6 @@ CEntity::~CEntity(void)
}
void
-CEntity::GetBoundCentre(CVector &out)
-{
- out = m_matrix * CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.center;
-};
-
-bool
-CEntity::GetIsTouching(CVector const &center, float radius)
-{
- return sq(GetBoundRadius()+radius) > (GetBoundCentre()-center).MagnitudeSqr();
-}
-
-bool
-CEntity::GetIsOnScreen(void)
-{
- return TheCamera.IsSphereVisible(GetBoundCentre(), GetBoundRadius(),
- &TheCamera.GetCameraMatrix());
-}
-
-bool
-CEntity::GetIsOnScreenComplex(void)
-{
- RwV3d boundBox[8];
-
- if(TheCamera.IsPointVisible(GetBoundCentre(), &TheCamera.GetCameraMatrix()))
- return true;
-
- CRect rect = GetBoundRect();
- CColModel *colmodel = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
- float z = GetPosition().z;
- float minz = z + colmodel->boundingBox.min.z;
- float maxz = z + colmodel->boundingBox.max.z;
- boundBox[0].x = rect.left;
- boundBox[0].y = rect.bottom;
- boundBox[0].z = minz;
- boundBox[1].x = rect.left;
- boundBox[1].y = rect.top;
- boundBox[1].z = minz;
- boundBox[2].x = rect.right;
- boundBox[2].y = rect.bottom;
- boundBox[2].z = minz;
- boundBox[3].x = rect.right;
- boundBox[3].y = rect.top;
- boundBox[3].z = minz;
- boundBox[4].x = rect.left;
- boundBox[4].y = rect.bottom;
- boundBox[4].z = maxz;
- boundBox[5].x = rect.left;
- boundBox[5].y = rect.top;
- boundBox[5].z = maxz;
- boundBox[6].x = rect.right;
- boundBox[6].y = rect.bottom;
- boundBox[6].z = maxz;
- boundBox[7].x = rect.right;
- boundBox[7].y = rect.top;
- boundBox[7].z = maxz;
-
- return TheCamera.IsBoxVisible(boundBox, &TheCamera.GetCameraMatrix());
-}
-
-void
-CEntity::Add(void)
-{
- int x, xstart, xmid, xend;
- int y, ystart, ymid, yend;
- CSector *s;
- CPtrList *list;
-
- CRect bounds = GetBoundRect();
- xstart = CWorld::GetSectorIndexX(bounds.left);
- xend = CWorld::GetSectorIndexX(bounds.right);
- xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);
- ystart = CWorld::GetSectorIndexY(bounds.top);
- yend = CWorld::GetSectorIndexY(bounds.bottom);
- ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
- assert(xstart >= 0);
- assert(xend < NUMSECTORS_X);
- assert(ystart >= 0);
- assert(yend < NUMSECTORS_Y);
-
- for(y = ystart; y <= yend; y++)
- for(x = xstart; x <= xend; x++){
- s = CWorld::GetSector(x, y);
- if(x == xmid && y == ymid) switch(m_type){
- case ENTITY_TYPE_BUILDING:
- list = &s->m_lists[ENTITYLIST_BUILDINGS];
- break;
- case ENTITY_TYPE_VEHICLE:
- list = &s->m_lists[ENTITYLIST_VEHICLES];
- break;
- case ENTITY_TYPE_PED:
- list = &s->m_lists[ENTITYLIST_PEDS];
- break;
- case ENTITY_TYPE_OBJECT:
- list = &s->m_lists[ENTITYLIST_OBJECTS];
- break;
- case ENTITY_TYPE_DUMMY:
- list = &s->m_lists[ENTITYLIST_DUMMIES];
- break;
- }else switch(m_type){
- case ENTITY_TYPE_BUILDING:
- list = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];
- break;
- case ENTITY_TYPE_VEHICLE:
- list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];
- break;
- case ENTITY_TYPE_PED:
- list = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];
- break;
- case ENTITY_TYPE_OBJECT:
- list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
- break;
- case ENTITY_TYPE_DUMMY:
- list = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];
- break;
- }
- list->InsertItem(this);
- }
-}
-
-void
-CEntity::Remove(void)
-{
- int x, xstart, xmid, xend;
- int y, ystart, ymid, yend;
- CSector *s;
- CPtrList *list;
-
- CRect bounds = GetBoundRect();
- xstart = CWorld::GetSectorIndexX(bounds.left);
- xend = CWorld::GetSectorIndexX(bounds.right);
- xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);
- ystart = CWorld::GetSectorIndexY(bounds.top);
- yend = CWorld::GetSectorIndexY(bounds.bottom);
- ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
- assert(xstart >= 0);
- assert(xend < NUMSECTORS_X);
- assert(ystart >= 0);
- assert(yend < NUMSECTORS_Y);
-
- for(y = ystart; y <= yend; y++)
- for(x = xstart; x <= xend; x++){
- s = CWorld::GetSector(x, y);
- if(x == xmid && y == ymid) switch(m_type){
- case ENTITY_TYPE_BUILDING:
- list = &s->m_lists[ENTITYLIST_BUILDINGS];
- break;
- case ENTITY_TYPE_VEHICLE:
- list = &s->m_lists[ENTITYLIST_VEHICLES];
- break;
- case ENTITY_TYPE_PED:
- list = &s->m_lists[ENTITYLIST_PEDS];
- break;
- case ENTITY_TYPE_OBJECT:
- list = &s->m_lists[ENTITYLIST_OBJECTS];
- break;
- case ENTITY_TYPE_DUMMY:
- list = &s->m_lists[ENTITYLIST_DUMMIES];
- break;
- }else switch(m_type){
- case ENTITY_TYPE_BUILDING:
- list = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];
- break;
- case ENTITY_TYPE_VEHICLE:
- list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];
- break;
- case ENTITY_TYPE_PED:
- list = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];
- break;
- case ENTITY_TYPE_OBJECT:
- list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
- break;
- case ENTITY_TYPE_DUMMY:
- list = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];
- break;
- }
- list->RemoveItem(this);
- }
-}
-
-void
CEntity::SetModelIndex(uint32 id)
{
m_modelIndex = id;
@@ -319,6 +131,48 @@ CEntity::CreateRwObject(void)
}
void
+CEntity::AttachToRwObject(RwObject *obj)
+{
+ m_rwObject = obj;
+ if(m_rwObject){
+ if(RwObjectGetType(m_rwObject) == rpATOMIC)
+ m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
+ else if(RwObjectGetType(m_rwObject) == rpCLUMP)
+ m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
+ CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
+ }
+}
+
+void
+CEntity::DetachFromRwObject(void)
+{
+ if(m_rwObject)
+ CModelInfo::GetModelInfo(m_modelIndex)->RemoveRef();
+ m_rwObject = nil;
+ m_matrix.Detach();
+}
+
+RpAtomic*
+AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data)
+{
+ if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){
+ RpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic);
+#ifdef LIBRW
+ if(hier && hier->interpolator->currentAnim){
+ RpHAnimAnimationDestroy(hier->interpolator->currentAnim);
+ hier->interpolator->currentAnim = nil;
+ }
+#else
+ if(hier && hier->currentAnim){
+ RpHAnimAnimationDestroy(hier->currentAnim->pCurrentAnim);
+ hier->currentAnim = nil;
+ }
+#endif
+ }
+ return atomic;
+}
+
+void
CEntity::DeleteRwObject(void)
{
RwFrame *f;
@@ -341,35 +195,6 @@ CEntity::DeleteRwObject(void)
}
}
-void
-CEntity::UpdateRwFrame(void)
-{
- if(m_rwObject){
- if(RwObjectGetType(m_rwObject) == rpATOMIC)
- RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
- else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
- }
-}
-
-void
-CEntity::SetupBigBuilding(void)
-{
- CSimpleModelInfo *mi;
-
- mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);
- bIsBIGBuilding = true;
- bStreamingDontDelete = true;
- bUsesCollision = false;
- m_level = CTheZones::GetLevelFromPosition(&GetPosition());
- if(mi->m_lodDistances[0] <= 2000.0f)
- bStreamBIGBuilding = true;
- if(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist)
- m_level = LEVEL_GENERIC;
- else if(m_level == LEVEL_GENERIC)
- printf("%s isn't in a level\n", mi->GetName());
-}
-
CRect
CEntity::GetBoundRect(void)
{
@@ -391,6 +216,74 @@ CEntity::GetBoundRect(void)
return rect;
}
+CVector
+CEntity::GetBoundCentre(void)
+{
+ CVector v;
+ GetBoundCentre(v);
+ return v;
+}
+
+void
+CEntity::GetBoundCentre(CVector &out)
+{
+ out = m_matrix * CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.center;
+}
+
+float
+CEntity::GetBoundRadius(void)
+{
+ return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.radius;
+}
+
+void
+CEntity::UpdateRwFrame(void)
+{
+ if(m_rwObject){
+ if(RwObjectGetType(m_rwObject) == rpATOMIC)
+ RwFrameUpdateObjects(RpAtomicGetFrame((RpAtomic*)m_rwObject));
+ else if(RwObjectGetType(m_rwObject) == rpCLUMP)
+ RwFrameUpdateObjects(RpClumpGetFrame((RpClump*)m_rwObject));
+ }
+}
+
+void
+CEntity::UpdateRpHAnim(void)
+{
+ if(IsClumpSkinned(GetClump())){
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ RpHAnimHierarchyUpdateMatrices(hier);
+#if 0
+ int i;
+ char buf[256];
+ if(this == (CEntity*)FindPlayerPed())
+ for(i = 0; i < hier->numNodes; i++){
+ RpHAnimStdInterpFrame *kf = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i);
+ sprintf(buf, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %d %s",
+ kf->q.imag.x, kf->q.imag.y, kf->q.imag.z, kf->q.real,
+ kf->t.x, kf->t.y, kf->t.z,
+ HIERNODEID(hier, i),
+ ConvertBoneTag2BoneName(HIERNODEID(hier, i)));
+ CDebug::PrintAt(buf, 10, 1+i*3);
+
+ RwMatrix *m = &RpHAnimHierarchyGetMatrixArray(hier)[i];
+ sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
+ m->right.x, m->up.x, m->at.x, m->pos.x);
+ CDebug::PrintAt(buf, 80, 1+i*3+0);
+ sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
+ m->right.y, m->up.y, m->at.y, m->pos.y);
+ CDebug::PrintAt(buf, 80, 1+i*3+1);
+ sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
+ m->right.z, m->up.z, m->at.z, m->pos.z);
+ CDebug::PrintAt(buf, 80, 1+i*3+2);
+ }
+
+ void RenderSkeleton(RpHAnimHierarchy *hier);
+ RenderSkeleton(hier);
+#endif
+ }
+}
+
bool
CEntity::HasPreRenderEffects(void)
{
@@ -516,15 +409,6 @@ CEntity::PreRender(void)
}
void
-CEntity::PreRenderForGlassWindow(void)
-{
- if(((CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_isArtistGlass)
- return;
- CGlass::AskForObjectToBeRenderedInGlass(this);
- bIsVisible = false;
-}
-
-void
CEntity::Render(void)
{
if(m_rwObject){
@@ -538,416 +422,213 @@ CEntity::Render(void)
}
bool
-CEntity::SetupLighting(void)
+CEntity::GetIsTouching(CVector const &center, float radius)
{
- return false;
+ return sq(GetBoundRadius()+radius) > (GetBoundCentre()-center).MagnitudeSqr();
}
-void
-CEntity::AttachToRwObject(RwObject *obj)
+bool
+CEntity::IsVisible(void)
{
- m_rwObject = obj;
- if(m_rwObject){
- if(RwObjectGetType(m_rwObject) == rpATOMIC)
- m_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);
- else if(RwObjectGetType(m_rwObject) == rpCLUMP)
- m_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);
- CModelInfo::GetModelInfo(m_modelIndex)->AddRef();
- }
+ return m_rwObject && bIsVisible && GetIsOnScreen();
}
-void
-CEntity::DetachFromRwObject(void)
+bool
+CEntity::IsVisibleComplex(void)
{
- if(m_rwObject)
- CModelInfo::GetModelInfo(m_modelIndex)->RemoveRef();
- m_rwObject = nil;
- m_matrix.Detach();
+ return m_rwObject && bIsVisible && GetIsOnScreenComplex();
}
-void
-CEntity::RegisterReference(CEntity **pent)
+bool
+CEntity::GetIsOnScreen(void)
{
- if(IsBuilding())
- return;
- CReference *ref;
- // check if already registered
- for(ref = m_pFirstReference; ref; ref = ref->next)
- if(ref->pentity == pent)
- return;
- // have to allocate new reference
- ref = CReferences::pEmptyList;
- if(ref){
- CReferences::pEmptyList = ref->next;
-
- ref->pentity = pent;
- ref->next = m_pFirstReference;
- m_pFirstReference = ref;
- return;
- }
- return;
+ return TheCamera.IsSphereVisible(GetBoundCentre(), GetBoundRadius(),
+ &TheCamera.GetCameraMatrix());
}
-// Clear all references to this entity
-void
-CEntity::ResolveReferences(void)
+bool
+CEntity::GetIsOnScreenComplex(void)
{
- CReference *ref;
- // clear pointers to this entity
- for(ref = m_pFirstReference; ref; ref = ref->next)
- if(*ref->pentity == this)
- *ref->pentity = nil;
- // free list
- if(m_pFirstReference){
- for(ref = m_pFirstReference; ref->next; ref = ref->next)
- ;
- ref->next = CReferences::pEmptyList;
- CReferences::pEmptyList = m_pFirstReference;
- m_pFirstReference = nil;
- }
-}
+ RwV3d boundBox[8];
-// Free all references that no longer point to this entity
-void
-CEntity::PruneReferences(void)
-{
- CReference *ref, *next, **lastnextp;
- lastnextp = &m_pFirstReference;
- for(ref = m_pFirstReference; ref; ref = next){
- next = ref->next;
- if(*ref->pentity == this)
- lastnextp = &ref->next;
- else{
- *lastnextp = ref->next;
- ref->next = CReferences::pEmptyList;
- CReferences::pEmptyList = ref;
- }
- }
-}
+ if(TheCamera.IsPointVisible(GetBoundCentre(), &TheCamera.GetCameraMatrix()))
+ return true;
-// Clean up the reference from *pent -> 'this'
-void
-CEntity::CleanUpOldReference(CEntity **pent)
-{
- CReference* ref, ** lastnextp;
- lastnextp = &m_pFirstReference;
- for (ref = m_pFirstReference; ref; ref = ref->next) {
- if (ref->pentity == pent) {
- *lastnextp = ref->next;
- ref->next = CReferences::pEmptyList;
- CReferences::pEmptyList = ref;
- break;
- }
- lastnextp = &ref->next;
- }
+ CRect rect = GetBoundRect();
+ CColModel *colmodel = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
+ float z = GetPosition().z;
+ float minz = z + colmodel->boundingBox.min.z;
+ float maxz = z + colmodel->boundingBox.max.z;
+ boundBox[0].x = rect.left;
+ boundBox[0].y = rect.bottom;
+ boundBox[0].z = minz;
+ boundBox[1].x = rect.left;
+ boundBox[1].y = rect.top;
+ boundBox[1].z = minz;
+ boundBox[2].x = rect.right;
+ boundBox[2].y = rect.bottom;
+ boundBox[2].z = minz;
+ boundBox[3].x = rect.right;
+ boundBox[3].y = rect.top;
+ boundBox[3].z = minz;
+ boundBox[4].x = rect.left;
+ boundBox[4].y = rect.bottom;
+ boundBox[4].z = maxz;
+ boundBox[5].x = rect.left;
+ boundBox[5].y = rect.top;
+ boundBox[5].z = maxz;
+ boundBox[6].x = rect.right;
+ boundBox[6].y = rect.bottom;
+ boundBox[6].z = maxz;
+ boundBox[7].x = rect.right;
+ boundBox[7].y = rect.top;
+ boundBox[7].z = maxz;
+
+ return TheCamera.IsBoxVisible(boundBox, &TheCamera.GetCameraMatrix());
}
void
-CEntity::UpdateRpHAnim(void)
+CEntity::Add(void)
{
- if(IsClumpSkinned(GetClump())){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- RpHAnimHierarchyUpdateMatrices(hier);
-#if 0
- int i;
- char buf[256];
- if(this == (CEntity*)FindPlayerPed())
- for(i = 0; i < hier->numNodes; i++){
- RpHAnimStdInterpFrame *kf = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i);
- sprintf(buf, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %d %s",
- kf->q.imag.x, kf->q.imag.y, kf->q.imag.z, kf->q.real,
- kf->t.x, kf->t.y, kf->t.z,
- HIERNODEID(hier, i),
- ConvertBoneTag2BoneName(HIERNODEID(hier, i)));
- CDebug::PrintAt(buf, 10, 1+i*3);
-
- RwMatrix *m = &RpHAnimHierarchyGetMatrixArray(hier)[i];
- sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
- m->right.x, m->up.x, m->at.x, m->pos.x);
- CDebug::PrintAt(buf, 80, 1+i*3+0);
- sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
- m->right.y, m->up.y, m->at.y, m->pos.y);
- CDebug::PrintAt(buf, 80, 1+i*3+1);
- sprintf(buf, "%6.3f %6.3f %6.3f %6.3f",
- m->right.z, m->up.z, m->at.z, m->pos.z);
- CDebug::PrintAt(buf, 80, 1+i*3+2);
- }
+ int x, xstart, xmid, xend;
+ int y, ystart, ymid, yend;
+ CSector *s;
+ CPtrList *list;
- void RenderSkeleton(RpHAnimHierarchy *hier);
- RenderSkeleton(hier);
-#endif
- }
-}
+ CRect bounds = GetBoundRect();
+ xstart = CWorld::GetSectorIndexX(bounds.left);
+ xend = CWorld::GetSectorIndexX(bounds.right);
+ xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);
+ ystart = CWorld::GetSectorIndexY(bounds.top);
+ yend = CWorld::GetSectorIndexY(bounds.bottom);
+ ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
+ assert(xstart >= 0);
+ assert(xend < NUMSECTORS_X);
+ assert(ystart >= 0);
+ assert(yend < NUMSECTORS_Y);
-void
-CEntity::AddSteamsFromGround(CVector *unused)
-{
- int i, n;
- C2dEffect *effect;
- CVector pos;
-
- n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();
- for(i = 0; i < n; i++){
- effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
- if(effect->type != EFFECT_PARTICLE)
- continue;
-
- pos = GetMatrix() * effect->pos;
- switch(effect->particle.particleType){
- case 0:
- CParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
- break;
- case 1:
- CParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
- break;
- case 2:
- CParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false);
- break;
- case 3:
- CParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false);
- break;
- case 4:
- CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false);
- break;
- case 5:
- CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_VERT, pos, effect->particle.dir, effect->particle.scale, false);
- break;
- case 6:
- CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_HORIZ, pos, effect->particle.dir, effect->particle.scale, false);
- break;
+ for(y = ystart; y <= yend; y++)
+ for(x = xstart; x <= xend; x++){
+ s = CWorld::GetSector(x, y);
+ if(x == xmid && y == ymid) switch(m_type){
+ case ENTITY_TYPE_BUILDING:
+ list = &s->m_lists[ENTITYLIST_BUILDINGS];
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ list = &s->m_lists[ENTITYLIST_VEHICLES];
+ break;
+ case ENTITY_TYPE_PED:
+ list = &s->m_lists[ENTITYLIST_PEDS];
+ break;
+ case ENTITY_TYPE_OBJECT:
+ list = &s->m_lists[ENTITYLIST_OBJECTS];
+ break;
+ case ENTITY_TYPE_DUMMY:
+ list = &s->m_lists[ENTITYLIST_DUMMIES];
+ break;
+ }else switch(m_type){
+ case ENTITY_TYPE_BUILDING:
+ list = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];
+ break;
+ case ENTITY_TYPE_PED:
+ list = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];
+ break;
+ case ENTITY_TYPE_OBJECT:
+ list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
+ break;
+ case ENTITY_TYPE_DUMMY:
+ list = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];
+ break;
+ }
+ list->InsertItem(this);
}
- }
}
void
-CEntity::ProcessLightsForEntity(void)
+CEntity::Remove(void)
{
- int i, n;
- C2dEffect *effect;
- CVector pos;
- bool lightOn, lightFlickering;
- uint32 flashTimer1, flashTimer2, flashTimer3;
-
- if(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)
- return;
-
- flashTimer1 = 0;
- flashTimer2 = 0;
- flashTimer3 = 0;
-
- n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();
- for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){
- effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
+ int x, xstart, xmid, xend;
+ int y, ystart, ymid, yend;
+ CSector *s;
+ CPtrList *list;
- switch(effect->type){
- case EFFECT_LIGHT:
- pos = GetMatrix() * effect->pos;
+ CRect bounds = GetBoundRect();
+ xstart = CWorld::GetSectorIndexX(bounds.left);
+ xend = CWorld::GetSectorIndexX(bounds.right);
+ xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);
+ ystart = CWorld::GetSectorIndexY(bounds.top);
+ yend = CWorld::GetSectorIndexY(bounds.bottom);
+ ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
+ assert(xstart >= 0);
+ assert(xend < NUMSECTORS_X);
+ assert(ystart >= 0);
+ assert(yend < NUMSECTORS_Y);
- lightOn = false;
- lightFlickering = false;
- switch(effect->light.lightType){
- case LIGHT_ON:
- lightOn = true;
- break;
- case LIGHT_ON_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
- lightOn = true;
- break;
- case LIGHT_FLICKER:
- if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
- lightOn = true;
- else
- lightFlickering = true;
- if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
- lightOn = true;
- break;
- case LIGHT_FLICKER_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){
- if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
- lightOn = true;
- else
- lightFlickering = true;
- if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
- lightOn = true;
- }
- break;
- case LIGHT_FLASH1:
- if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
- lightOn = true;
+ for(y = ystart; y <= yend; y++)
+ for(x = xstart; x <= xend; x++){
+ s = CWorld::GetSector(x, y);
+ if(x == xmid && y == ymid) switch(m_type){
+ case ENTITY_TYPE_BUILDING:
+ list = &s->m_lists[ENTITYLIST_BUILDINGS];
break;
- case LIGHT_FLASH1_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
- if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
- lightOn = true;
+ case ENTITY_TYPE_VEHICLE:
+ list = &s->m_lists[ENTITYLIST_VEHICLES];
break;
- case LIGHT_FLASH2:
- if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
- lightOn = true;
+ case ENTITY_TYPE_PED:
+ list = &s->m_lists[ENTITYLIST_PEDS];
break;
- case LIGHT_FLASH2_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
- if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
- lightOn = true;
+ case ENTITY_TYPE_OBJECT:
+ list = &s->m_lists[ENTITYLIST_OBJECTS];
break;
- case LIGHT_FLASH3:
- if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
- lightOn = true;
+ case ENTITY_TYPE_DUMMY:
+ list = &s->m_lists[ENTITYLIST_DUMMIES];
break;
- case LIGHT_FLASH3_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
- if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
- lightOn = true;
+ }else switch(m_type){
+ case ENTITY_TYPE_BUILDING:
+ list = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];
break;
- case LIGHT_RANDOM_FLICKER:
- if(m_randomSeed > 16)
- lightOn = true;
- else{
- if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
- lightOn = true;
- else
- lightFlickering = true;
- if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
- lightOn = true;
- }
+ case ENTITY_TYPE_VEHICLE:
+ list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];
break;
- case LIGHT_RANDOM_FLICKER_NIGHT:
- if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
- if(m_randomSeed > 16)
- lightOn = true;
- else{
- if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
- lightOn = true;
- else
- lightFlickering = true;
- if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
- lightOn = true;
- }
- }
+ case ENTITY_TYPE_PED:
+ list = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];
break;
- case LIGHT_BRIDGE_FLASH1:
- if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200)
- lightOn = true;
+ case ENTITY_TYPE_OBJECT:
+ list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
break;
- case LIGHT_BRIDGE_FLASH2:
- if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60)
- lightOn = true;
+ case ENTITY_TYPE_DUMMY:
+ list = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];
break;
}
+ list->RemoveItem(this);
+ }
+}
- if(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){
- if(lightOn)
- bDoNotRender = false;
- else
- bDoNotRender = true;
- return;
- }
-
- // Corona
- if(lightOn)
- CCoronas::RegisterCorona((uintptr)this + i,
- effect->col.r, effect->col.g, effect->col.b, 255,
- pos, effect->light.size, effect->light.dist,
- effect->light.corona, effect->light.flareType, effect->light.roadReflection,
- effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
- !!(effect->light.flags&LIGHTFLAG_LONG_DIST));
- else if(lightFlickering)
- CCoronas::RegisterCorona((uintptr)this + i,
- 0, 0, 0, 255,
- pos, effect->light.size, effect->light.dist,
- effect->light.corona, effect->light.flareType, effect->light.roadReflection,
- effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
- !!(effect->light.flags&LIGHTFLAG_LONG_DIST));
-
- // Pointlight
- bool alreadyProcessedFog;
- alreadyProcessedFog = false;
- if(effect->light.range != 0.0f && lightOn){
- if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){
- CPointLights::AddLight(CPointLights::LIGHT_POINT,
- pos, CVector(0.0f, 0.0f, 0.0f),
- effect->light.range,
- 0.0f, 0.0f, 0.0f,
- CPointLights::FOG_NONE, true);
- }else{
- CPointLights::AddLight(CPointLights::LIGHT_POINT,
- pos, CVector(0.0f, 0.0f, 0.0f),
- effect->light.range,
- effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f,
- effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f,
- effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f,
- (effect->light.flags & LIGHTFLAG_FOG) >> 1,
- true);
- alreadyProcessedFog = true;
- }
- }
-
- if(!alreadyProcessedFog){
- if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){
- CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS,
- pos, CVector(0.0f, 0.0f, 0.0f),
- 0.0f,
- effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
- CPointLights::FOG_ALWAYS, true);
- }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){
- CPointLights::AddLight(CPointLights::LIGHT_FOGONLY,
- pos, CVector(0.0f, 0.0f, 0.0f),
- 0.0f,
- effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
- CPointLights::FOG_NORMAL, true);
- }
- }
+float
+CEntity::GetDistanceFromCentreOfMassToBaseOfModel(void)
+{
+ return -CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingBox.min.z;
+}
- // Light shadow
- if(effect->light.shadowSize != 0.0f){
- if(lightOn){
- CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
- effect->light.shadow, &pos,
- effect->light.shadowSize, 0.0f,
- 0.0f, -effect->light.shadowSize,
- 128,
- effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
- effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
- effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
- 15.0f, 1.0f, 40.0f, false, 0.0f);
- }else if(lightFlickering){
- CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
- effect->light.shadow, &pos,
- effect->light.shadowSize, 0.0f,
- 0.0f, -effect->light.shadowSize,
- 0, 0.0f, 0.0f, 0.0f,
- 15.0f, 1.0f, 40.0f, false, 0.0f);
- }
- }
- break;
+void
+CEntity::SetupBigBuilding(void)
+{
+ CSimpleModelInfo *mi;
- case EFFECT_SUNGLARE:
- if(CWeather::SunGlare >= 0.0f){
- CVector pos = GetMatrix() * effect->pos;
- CVector glareDir = pos - GetPosition();
- glareDir.Normalise();
- CVector camDir = TheCamera.GetPosition() - pos;
- float dist = camDir.Magnitude();
- camDir *= 2.0f/dist;
- glareDir += camDir;
- glareDir.Normalise();
- float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection());
- if(camAngle > 0.0f){
- float intens = Sqrt(camAngle) * CWeather::SunGlare;
- pos += camDir;
- CCoronas::RegisterCorona((uintptr)this + 33 + i,
- intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f,
- intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f,
- intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f,
- 255,
- pos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f,
- CCoronas::TYPE_STAR, CCoronas::FLARE_NONE,
- CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,
- CCoronas::STREAK_OFF, 0.0f);
- }
- }
- break;
- }
- }
+ mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);
+ bIsBIGBuilding = true;
+ bStreamingDontDelete = true;
+ bUsesCollision = false;
+ m_level = CTheZones::GetLevelFromPosition(&GetPosition());
+ if(mi->m_lodDistances[0] <= 2000.0f)
+ bStreamBIGBuilding = true;
+ if(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist)
+ m_level = LEVEL_GENERIC;
+ else if(m_level == LEVEL_GENERIC)
+ printf("%s isn't in a level\n", mi->GetName());
}
float WindTabel[] = {
@@ -1041,14 +722,67 @@ CEntity::ModifyMatrixForBannerInWind(void)
UpdateRwFrame();
}
-void
-CEntity::AddSteamsFromGround(CPtrList& list)
+void
+CEntity::PreRenderForGlassWindow(void)
+{
+ if(((CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_isArtistGlass)
+ return;
+ CGlass::AskForObjectToBeRenderedInGlass(this);
+ bIsVisible = false;
+}
+
+/*
+0x487A10 - SetAtomicAlphaCB
+0x4879E0 - SetClumpAlphaCB
+*/
+
+RpMaterial*
+SetAtomicAlphaCB(RpMaterial *material, void *data)
{
- CPtrNode *pNode = list.first;
- while (pNode) {
- ((CEntity*)pNode->item)->AddSteamsFromGround(nil);
- pNode = pNode->next;
+ ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;
+ return material;
+}
+
+RpAtomic*
+SetClumpAlphaCB(RpAtomic *atomic, void *data)
+{
+ RpGeometry *geometry = RpAtomicGetGeometry(atomic);
+ RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
+ RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)data);
+ return atomic;
+}
+
+void
+CEntity::SetRwObjectAlpha(int32 alpha)
+{
+ if (m_rwObject != nil) {
+ switch (RwObjectGetType(m_rwObject)) {
+ case rpATOMIC: {
+ RpGeometry *geometry = RpAtomicGetGeometry((RpAtomic*)m_rwObject);
+ RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
+ RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)alpha);
+ break;
+ }
+ case rpCLUMP:
+ RpClumpForAllAtomics((RpClump*)m_rwObject, SetClumpAlphaCB, (void*)alpha);
+ break;
+ }
+ }
+}
+
+bool IsEntityPointerValid(CEntity* pEntity)
+{
+ if (!pEntity)
+ return false;
+ switch (pEntity->GetType()) {
+ case ENTITY_TYPE_NOTHING: return false;
+ case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);
+ case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);
+ case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);
+ case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);
+ case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);
}
+ return false;
}
#ifdef COMPATIBLE_SAVES
@@ -1165,84 +899,3 @@ CEntity::LoadEntityFlags(uint8*& buf)
}
#endif
-
-bool IsEntityPointerValid(CEntity* pEntity)
-{
- if (!pEntity)
- return false;
- switch (pEntity->GetType()) {
- case ENTITY_TYPE_NOTHING: return false;
- case ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);
- case ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);
- case ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);
- case ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);
- case ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);
- }
- return false;
-}
-
-bool CEntity::IsEntityOccluded(void) {
-
- CVector coors;
- float width, height;
-
- if (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height))
- return false;
-
- float area = Max(width, height) * GetBoundRadius() * 0.9f;
-
- for (int i = 0; i < COcclusion::NumActiveOccluders; i++) {
- if (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) {
- if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) {
- return true;
- }
-
- if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {
- CVector min = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.min;
- CVector max = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.max;
-
- if (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
- if (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
- if (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
- if (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
-
- return true;
- }
- }
- }
-
- return false;
-}
-
-/*
-0x487A10 - SetAtomicAlphaCB
-0x4879E0 - SetClumpAlphaCB
-*/
-
-RpMaterial* SetAtomicAlphaCB(RpMaterial *material, void *data) {
- ((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;
- return material;
-}
-
-RpAtomic* SetClumpAlphaCB(RpAtomic *atomic, void *data) {
- RpGeometry *geometry = RpAtomicGetGeometry(atomic);
- RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
- RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)data);
- return atomic;
-}
-
-void CEntity::SetRwObjectAlpha(int32 alpha) {
- if (m_rwObject != nil) {
- switch (RwObjectGetType(m_rwObject)) {
- case rpATOMIC: {
- RpGeometry *geometry = RpAtomicGetGeometry((RpAtomic*)m_rwObject);
- RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
- RpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)alpha);
- break;
- }
- case rpCLUMP:
- RpClumpForAllAtomics((RpClump*)m_rwObject, SetClumpAlphaCB, (void*)alpha);
- break;
- }
- }
-} \ No newline at end of file
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 9129457c..2749e3f7 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -130,7 +130,7 @@ public:
virtual void PreRender(void);
virtual void Render(void);
virtual bool SetupLighting(void);
- virtual void RemoveLighting(bool) {}
+ virtual void RemoveLighting(bool);
virtual void FlagToDestroyWhenNextProcessed(void) {}
bool IsBuilding(void) { return m_type == ENTITY_TYPE_BUILDING; }
@@ -149,14 +149,14 @@ public:
}
void GetBoundCentre(CVector &out);
- CVector GetBoundCentre(void) { CVector v; GetBoundCentre(v); return v; }
- float GetBoundRadius(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.radius; }
- float GetDistanceFromCentreOfMassToBaseOfModel(void) { return -CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingBox.min.z; }
+ CVector GetBoundCentre(void);
+ float GetBoundRadius(void);
+ float GetDistanceFromCentreOfMassToBaseOfModel(void);
bool GetIsTouching(CVector const &center, float r);
bool GetIsOnScreen(void);
bool GetIsOnScreenComplex(void);
- bool IsVisible(void) { return m_rwObject && bIsVisible && GetIsOnScreen(); }
- bool IsVisibleComplex(void) { return m_rwObject && bIsVisible && GetIsOnScreenComplex(); }
+ bool IsVisible(void);
+ bool IsVisibleComplex(void);
bool IsEntityOccluded(void);
int16 GetModelIndex(void) const { return m_modelIndex; }
void UpdateRwFrame(void);
@@ -179,8 +179,6 @@ public:
void ModifyMatrixForBannerInWind(void);
void ProcessLightsForEntity(void);
void SetRwObjectAlpha(int32 alpha);
-
- static void AddSteamsFromGround(CPtrList& list);
};
bool IsEntityPointerValid(CEntity*);
diff --git a/src/render/Coronas.cpp b/src/render/Coronas.cpp
index 9c87e2e0..515e1000 100644
--- a/src/render/Coronas.cpp
+++ b/src/render/Coronas.cpp
@@ -2,6 +2,7 @@
#include "main.h"
#include "General.h"
+#include "Entity.h"
#include "RenderBuffer.h"
#include "TxdStore.h"
#include "Camera.h"
@@ -12,6 +13,10 @@
#include "Collision.h"
#include "Timecycle.h"
#include "Coronas.h"
+#include "PointLights.h"
+#include "Shadows.h"
+#include "Clock.h"
+#include "Bridge.h"
//--MIAMI: file done
@@ -715,3 +720,234 @@ CRegisteredCorona::Update(void)
firstUpdate = false;
registeredThisFrame = false;
}
+
+void
+CEntity::ProcessLightsForEntity(void)
+{
+ int i, n;
+ C2dEffect *effect;
+ CVector pos;
+ bool lightOn, lightFlickering;
+ uint32 flashTimer1, flashTimer2, flashTimer3;
+
+ if(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)
+ return;
+
+ flashTimer1 = 0;
+ flashTimer2 = 0;
+ flashTimer3 = 0;
+
+ n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();
+ for(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){
+ effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
+
+ switch(effect->type){
+ case EFFECT_LIGHT:
+ pos = GetMatrix() * effect->pos;
+
+ lightOn = false;
+ lightFlickering = false;
+ switch(effect->light.lightType){
+ case LIGHT_ON:
+ lightOn = true;
+ break;
+ case LIGHT_ON_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
+ lightOn = true;
+ break;
+ case LIGHT_FLICKER:
+ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
+ lightOn = true;
+ else
+ lightFlickering = true;
+ if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
+ lightOn = true;
+ break;
+ case LIGHT_FLICKER_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){
+ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)
+ lightOn = true;
+ else
+ lightFlickering = true;
+ if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)
+ lightOn = true;
+ }
+ break;
+ case LIGHT_FLASH1:
+ if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
+ lightOn = true;
+ break;
+ case LIGHT_FLASH1_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
+ if((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)
+ lightOn = true;
+ break;
+ case LIGHT_FLASH2:
+ if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
+ lightOn = true;
+ break;
+ case LIGHT_FLASH2_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
+ if((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)
+ lightOn = true;
+ break;
+ case LIGHT_FLASH3:
+ if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
+ lightOn = true;
+ break;
+ case LIGHT_FLASH3_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7)
+ if((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)
+ lightOn = true;
+ break;
+ case LIGHT_RANDOM_FLICKER:
+ if(m_randomSeed > 16)
+ lightOn = true;
+ else{
+ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
+ lightOn = true;
+ else
+ lightFlickering = true;
+ if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
+ lightOn = true;
+ }
+ break;
+ case LIGHT_RANDOM_FLICKER_NIGHT:
+ if(CClock::GetHours() > 18 || CClock::GetHours() < 7){
+ if(m_randomSeed > 16)
+ lightOn = true;
+ else{
+ if((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)
+ lightOn = true;
+ else
+ lightFlickering = true;
+ if((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)
+ lightOn = true;
+ }
+ }
+ break;
+ case LIGHT_BRIDGE_FLASH1:
+ if(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200)
+ lightOn = true;
+ break;
+ case LIGHT_BRIDGE_FLASH2:
+ if(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60)
+ lightOn = true;
+ break;
+ }
+
+ if(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){
+ if(lightOn)
+ bDoNotRender = false;
+ else
+ bDoNotRender = true;
+ return;
+ }
+
+ // Corona
+ if(lightOn)
+ CCoronas::RegisterCorona((uintptr)this + i,
+ effect->col.r, effect->col.g, effect->col.b, 255,
+ pos, effect->light.size, effect->light.dist,
+ effect->light.corona, effect->light.flareType, effect->light.roadReflection,
+ effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
+ !!(effect->light.flags&LIGHTFLAG_LONG_DIST));
+ else if(lightFlickering)
+ CCoronas::RegisterCorona((uintptr)this + i,
+ 0, 0, 0, 255,
+ pos, effect->light.size, effect->light.dist,
+ effect->light.corona, effect->light.flareType, effect->light.roadReflection,
+ effect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,
+ !!(effect->light.flags&LIGHTFLAG_LONG_DIST));
+
+ // Pointlight
+ bool alreadyProcessedFog;
+ alreadyProcessedFog = false;
+ if(effect->light.range != 0.0f && lightOn){
+ if(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){
+ CPointLights::AddLight(CPointLights::LIGHT_POINT,
+ pos, CVector(0.0f, 0.0f, 0.0f),
+ effect->light.range,
+ 0.0f, 0.0f, 0.0f,
+ CPointLights::FOG_NONE, true);
+ }else{
+ CPointLights::AddLight(CPointLights::LIGHT_POINT,
+ pos, CVector(0.0f, 0.0f, 0.0f),
+ effect->light.range,
+ effect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f,
+ effect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f,
+ effect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f,
+ (effect->light.flags & LIGHTFLAG_FOG) >> 1,
+ true);
+ alreadyProcessedFog = true;
+ }
+ }
+
+ if(!alreadyProcessedFog){
+ if(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){
+ CPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS,
+ pos, CVector(0.0f, 0.0f, 0.0f),
+ 0.0f,
+ effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
+ CPointLights::FOG_ALWAYS, true);
+ }else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){
+ CPointLights::AddLight(CPointLights::LIGHT_FOGONLY,
+ pos, CVector(0.0f, 0.0f, 0.0f),
+ 0.0f,
+ effect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,
+ CPointLights::FOG_NORMAL, true);
+ }
+ }
+
+ // Light shadow
+ if(effect->light.shadowSize != 0.0f){
+ if(lightOn){
+ CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
+ effect->light.shadow, &pos,
+ effect->light.shadowSize, 0.0f,
+ 0.0f, -effect->light.shadowSize,
+ 128,
+ effect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
+ effect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
+ effect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,
+ 15.0f, 1.0f, 40.0f, false, 0.0f);
+ }else if(lightFlickering){
+ CShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,
+ effect->light.shadow, &pos,
+ effect->light.shadowSize, 0.0f,
+ 0.0f, -effect->light.shadowSize,
+ 0, 0.0f, 0.0f, 0.0f,
+ 15.0f, 1.0f, 40.0f, false, 0.0f);
+ }
+ }
+ break;
+
+ case EFFECT_SUNGLARE:
+ if(CWeather::SunGlare >= 0.0f){
+ CVector pos = GetMatrix() * effect->pos;
+ CVector glareDir = pos - GetPosition();
+ glareDir.Normalise();
+ CVector camDir = TheCamera.GetPosition() - pos;
+ float dist = camDir.Magnitude();
+ camDir *= 2.0f/dist;
+ glareDir += camDir;
+ glareDir.Normalise();
+ float camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection());
+ if(camAngle > 0.0f){
+ float intens = Sqrt(camAngle) * CWeather::SunGlare;
+ pos += camDir;
+ CCoronas::RegisterCorona((uintptr)this + 33 + i,
+ intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f,
+ intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f,
+ intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f,
+ 255,
+ pos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f,
+ CCoronas::TYPE_STAR, CCoronas::FLARE_NONE,
+ CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,
+ CCoronas::STREAK_OFF, 0.0f);
+ }
+ }
+ break;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/render/Occlusion.cpp b/src/render/Occlusion.cpp
index 5fef6e21..2b15e75b 100644
--- a/src/render/Occlusion.cpp
+++ b/src/render/Occlusion.cpp
@@ -1,6 +1,7 @@
#include "common.h"
#include "main.h"
+#include "Entity.h"
#include "Occlusion.h"
#include "Game.h"
#include "Camera.h"
@@ -493,3 +494,36 @@ void COcclusion::Render() {
DefinedState();
}
#endif
+
+bool CEntity::IsEntityOccluded(void) {
+
+ CVector coors;
+ float width, height;
+
+ if (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height))
+ return false;
+
+ float area = Max(width, height) * GetBoundRadius() * 0.9f;
+
+ for (int i = 0; i < COcclusion::NumActiveOccluders; i++) {
+ if (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) {
+ if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) {
+ return true;
+ }
+
+ if (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {
+ CVector min = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.min;
+ CVector max = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.max;
+
+ if (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+ if (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/src/render/Particle.cpp b/src/render/Particle.cpp
index ebcaba67..0ad4681d 100644
--- a/src/render/Particle.cpp
+++ b/src/render/Particle.cpp
@@ -2472,3 +2472,43 @@ void CParticle::HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos)
}
}
+
+void
+CEntity::AddSteamsFromGround(CVector *unused)
+{
+ int i, n;
+ C2dEffect *effect;
+ CVector pos;
+
+ n = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();
+ for(i = 0; i < n; i++){
+ effect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);
+ if(effect->type != EFFECT_PARTICLE)
+ continue;
+
+ pos = GetMatrix() * effect->pos;
+ switch(effect->particle.particleType){
+ case 0:
+ CParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ case 1:
+ CParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ case 2:
+ CParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false);
+ break;
+ case 3:
+ CParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ case 4:
+ CParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ case 5:
+ CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_VERT, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ case 6:
+ CParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_HORIZ, pos, effect->particle.dir, effect->particle.scale, false);
+ break;
+ }
+ }
+}
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index e5c5a530..660b05fe 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -1497,6 +1497,17 @@ CRenderer::RequestObjectsInFrustum(void)
}
}
+bool
+CEntity::SetupLighting(void)
+{
+ return false;
+}
+
+void
+CEntity::RemoveLighting(bool)
+{
+}
+
// --MIAMI: Done
bool
CPed::SetupLighting(void)
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 2591a6dc..cab3b68c 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -289,26 +289,6 @@ HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier)
return anim;
}
-RpAtomic*
-AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data)
-{
- if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){
- RpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic);
-#ifdef LIBRW
- if(hier && hier->interpolator->currentAnim){
- RpHAnimAnimationDestroy(hier->interpolator->currentAnim);
- hier->interpolator->currentAnim = nil;
- }
-#else
- if(hier && hier->currentAnim){
- RpHAnimAnimationDestroy(hier->currentAnim->pCurrentAnim);
- hier->currentAnim = nil;
- }
-#endif
- }
- return atomic;
-}
-
void
RenderSkeleton(RpHAnimHierarchy *hier)
{