Skip to content

Commit 27210e3

Browse files
authored
Implement W3DPropBuffer (#792)
1 parent 84891b5 commit 27210e3

File tree

6 files changed

+370
-13
lines changed

6 files changed

+370
-13
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ set(GAMEENGINE_SRC
295295
platform/w3dengine/client/w3dgameclient.cpp
296296
platform/w3dengine/client/w3dpoly.cpp
297297
platform/w3dengine/client/w3dparticlesys.cpp
298+
platform/w3dengine/client/w3dpropbuffer.cpp
298299
platform/w3dengine/client/w3droadbuffer.cpp
299300
platform/w3dengine/client/w3dshroud.cpp
300301
platform/w3dengine/client/w3dsmudge.cpp

src/game/logic/system/partitionmanager.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ void PartitionManager::Remove_From_Dirty_Modules(PartitionData *data)
126126
}
127127

128128
// zh: 0x0053A820 wb: 0x0081CE95
129-
bool PartitionManager::Geom_Collides_With_Geom(Coord3D const *unk1,
130-
GeometryInfo const &unk2,
131-
float unk3,
132-
Coord3D const *unk4,
133-
GeometryInfo const &unk5,
134-
float unk6) const
129+
bool PartitionManager::Geom_Collides_With_Geom(Coord3D const *position,
130+
GeometryInfo const &geometry,
131+
float angle,
132+
Coord3D const *position2,
133+
GeometryInfo const &geometry2,
134+
float angle2) const
135135
{
136136
#ifdef GAME_DLL
137137
return Call_Method<bool,
@@ -141,7 +141,7 @@ bool PartitionManager::Geom_Collides_With_Geom(Coord3D const *unk1,
141141
float,
142142
Coord3D const *,
143143
GeometryInfo const &,
144-
float>(PICK_ADDRESS(0x0053A820, 0x0081CE95), this, unk1, unk2, unk3, unk4, unk5, unk6);
144+
float>(PICK_ADDRESS(0x0053A820, 0x0081CE95), this, position, geometry, angle, position2, geometry2, angle2);
145145
#else
146146
return false;
147147
#endif
@@ -804,3 +804,13 @@ bool PartitionFilterSameMapStatus::Allow(Object *obj)
804804
{
805805
return m_object->Is_Outside_Map() == obj->Is_Outside_Map();
806806
}
807+
808+
ObjectShroudStatus PartitionManager::Get_Prop_Shroud_Status_For_Player(int id, const Coord3D *position) const
809+
{
810+
#ifdef GAME_DLL
811+
return Call_Method<ObjectShroudStatus, const PartitionManager, int, const Coord3D *>(
812+
PICK_ADDRESS(0x0053C7F0, 0x0081F275), this, id, position);
813+
#else
814+
return SHROUDED_INVALID;
815+
#endif
816+
}

src/game/logic/system/partitionmanager.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,12 @@ class PartitionManager : public SubsystemInterface, public SnapShot
196196
virtual void Xfer_Snapshot(Xfer *xfer) override;
197197
virtual void Load_Post_Process() override{};
198198

199-
bool Geom_Collides_With_Geom(Coord3D const *unk1,
200-
GeometryInfo const &unk2,
201-
float unk3,
202-
Coord3D const *unk4,
203-
GeometryInfo const &unk5,
204-
float unk6) const;
199+
bool Geom_Collides_With_Geom(Coord3D const *position,
200+
GeometryInfo const &geometry,
201+
float angle,
202+
Coord3D const *position2,
203+
GeometryInfo const &geometry2,
204+
float angle2) const;
205205
int32_t Calc_Min_Radius(const ICoord2D &cur);
206206
void Calc_Radius_Vec();
207207
void Do_Shroud_Cover(float centerX, float centerY, float radius, uint16_t playerIndex);
@@ -248,6 +248,7 @@ class PartitionManager : public SubsystemInterface, public SnapShot
248248
Coord3D const *pos, float unk, DistanceCalculationType dc, PartitionFilter **filters, IterOrderType order);
249249
SimpleObjectIterator *Iterate_Potential_Collisions(Coord3D const *pos, GeometryInfo const &geom, float angle, bool unk);
250250
SimpleObjectIterator *Iterate_All_Objects(PartitionFilter **filters);
251+
ObjectShroudStatus Get_Prop_Shroud_Status_For_Player(int id, const Coord3D *position) const;
251252

252253
bool Find_Position_Around(Coord3D const *center, FindPositionOptions const *options, Coord3D *result);
253254

src/hooker/setuphooks_zh.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
#include "w3dmouse.h"
173173
#include "w3dpoly.h"
174174
#include "w3dprojectedshadow.h"
175+
#include "w3dpropbuffer.h"
175176
#include "w3droadbuffer.h"
176177
#include "w3dscene.h"
177178
#include "w3dshroud.h"
@@ -2426,4 +2427,14 @@ void Setup_Hooks()
24262427
Hook_Any(0x004469C0, FileSystem::Are_Music_Files_On_CD); // This one is part of the CD Check.
24272428
Hook_Any(0x00446BF0, FileSystem::Load_Music_Files_From_CD);
24282429
Hook_Any(0x00446D50, FileSystem::Unload_Music_Files_From_CD);
2430+
2431+
// w3dpropbuffer.h
2432+
Hook_Any(0x00797400, W3DPropBuffer::Hook_Dtor);
2433+
Hook_Any(0x007974D0, W3DPropBuffer::Hook_Ctor);
2434+
Hook_Any(0x00797600, W3DPropBuffer::Clear_All_Props);
2435+
Hook_Any(0x00797660, W3DPropBuffer::Add_Prop_Type);
2436+
Hook_Any(0x00797780, W3DPropBuffer::Add_Prop);
2437+
Hook_Any(0x00797A20, W3DPropBuffer::Remove_Props_For_Construction);
2438+
Hook_Any(0x00797B60, W3DPropBuffer::Notify_Shroud_Changed);
2439+
Hook_Any(0x00797BA0, W3DPropBuffer::Draw_Props);
24292440
}
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/**
2+
* @file
3+
*
4+
* @author Jonathan Wilson
5+
*
6+
* @brief Prop Drawing Code
7+
*
8+
* @copyright Thyme is free software: you can redistribute it and/or
9+
* modify it under the terms of the GNU General Public License
10+
* as published by the Free Software Foundation, either version
11+
* 2 of the License, or (at your option) any later version.
12+
* A full copy of the GNU General Public License can be found in
13+
* LICENSE
14+
*/
15+
#include "w3dpropbuffer.h"
16+
#include "assetmgr.h"
17+
#include "baseheightmap.h"
18+
#include "camera.h"
19+
#include "geometry.h"
20+
#include "globaldata.h"
21+
#include "light.h"
22+
#include "lightenv.h"
23+
#include "partitionmanager.h"
24+
#include "playerlist.h"
25+
#include "rinfo.h"
26+
#include "w3dshroud.h"
27+
28+
W3DPropBuffer::W3DPropBuffer() : m_propsUpdated(false), m_redoCull(false)
29+
{
30+
m_isInited = false;
31+
Clear_All_Props();
32+
m_light = new LightClass(LightClass::DIRECTIONAL);
33+
m_shroudMaterial = new W3DShroudMaterialPassClass();
34+
m_isInited = true;
35+
}
36+
37+
W3DPropBuffer::~W3DPropBuffer()
38+
{
39+
for (int i = 0; i < MAX_PROP_TYPES; i++) {
40+
Ref_Ptr_Release(m_propTypes[i].render_obj);
41+
}
42+
43+
Ref_Ptr_Release(m_light);
44+
Ref_Ptr_Release(m_shroudMaterial);
45+
}
46+
47+
void W3DPropBuffer::Cull(CameraClass *camera)
48+
{
49+
for (int i = 0; i < m_numProps; i++) {
50+
m_props[i].is_visible = !camera->Cull_Sphere(m_props[i].bounding_sphere);
51+
}
52+
}
53+
54+
void W3DPropBuffer::Clear_All_Props()
55+
{
56+
m_numProps = 0;
57+
58+
for (int i = 0; i < MAX_PROP_TYPES; i++) {
59+
Ref_Ptr_Release(m_propTypes[i].render_obj);
60+
m_propTypes[i].name.Clear();
61+
}
62+
63+
m_numPropTypes = 0;
64+
}
65+
66+
int W3DPropBuffer::Add_Prop_Type(const Utf8String &name)
67+
{
68+
if (m_numPropTypes >= MAX_PROP_TYPES) {
69+
captainslog_dbgassert(false, "Too many kinds of props in map. Reduce kinds of props, or raise prop limit.");
70+
return 0;
71+
} else {
72+
m_propTypes[m_numPropTypes].render_obj = W3DAssetManager::Get_Instance()->Create_Render_Obj(name.Str());
73+
74+
if (m_propTypes[m_numPropTypes].render_obj == nullptr) {
75+
captainslog_dbgassert(false, "Unable to find model for prop %s", name.Str());
76+
return -1;
77+
}
78+
79+
m_propTypes[m_numPropTypes].name = name;
80+
m_propTypes[m_numPropTypes].bounding_sphere = m_propTypes[m_numPropTypes].render_obj->Get_Bounding_Sphere();
81+
return m_numPropTypes++;
82+
}
83+
}
84+
85+
void W3DPropBuffer::Add_Prop(int id, Coord3D position, float orientation, float scale, const Utf8String &name)
86+
{
87+
if (m_numProps < MAX_PROPS && m_isInited) {
88+
int index = -1;
89+
90+
for (int i = 0; i < m_numPropTypes; i++) {
91+
if (m_propTypes[i].name.Compare_No_Case(name) == 0) {
92+
index = i;
93+
break;
94+
}
95+
}
96+
97+
if (index >= 0 || (index = Add_Prop_Type(name), index >= 0)) {
98+
Matrix3D tm(true);
99+
tm.Rotate_Z(orientation);
100+
tm.Scale(scale);
101+
tm.Set_Translation(Vector3(position.x, position.y, position.z));
102+
m_props[m_numProps].position = position;
103+
m_props[m_numProps].id = id;
104+
m_props[m_numProps].shroud_status = SHROUDED_INVALID;
105+
m_props[m_numProps].render_obj = m_propTypes[index].render_obj->Clone();
106+
m_props[m_numProps].render_obj->Set_Transform(tm);
107+
m_props[m_numProps].render_obj->Set_ObjectScale(scale);
108+
m_props[m_numProps].prop_type = index;
109+
m_props[m_numProps].bounding_sphere = m_propTypes[index].bounding_sphere;
110+
m_props[m_numProps].bounding_sphere.Center += Vector3(position.x, position.y, position.z);
111+
m_props[m_numProps].is_visible = false;
112+
m_numProps++;
113+
}
114+
}
115+
}
116+
117+
bool W3DPropBuffer::Update_Prop_Position(int id, const Coord3D &position, float orientation, float scale)
118+
{
119+
for (int i = 0; i < m_numProps; i++) {
120+
if (m_props[i].id == id) {
121+
Matrix3D tm(true);
122+
tm.Rotate_Z(orientation);
123+
tm.Scale(scale);
124+
tm.Set_Translation(Vector3(position.x, position.y, position.z));
125+
m_props[i].position = position;
126+
m_props[i].render_obj->Set_Transform(tm);
127+
m_props[i].render_obj->Set_ObjectScale(scale);
128+
m_props[i].bounding_sphere = m_propTypes[m_props[i].prop_type].bounding_sphere;
129+
m_props[i].bounding_sphere.Center += Vector3(position.x, position.y, position.z);
130+
m_propsUpdated = true;
131+
return true;
132+
}
133+
}
134+
135+
return false;
136+
}
137+
138+
void W3DPropBuffer::Remove_Prop(int id)
139+
{
140+
for (int i = 0; i < m_numProps; i++) {
141+
if (m_props[i].id == id) {
142+
m_props[i].position.Set(0.0f, 0.0f, 0.0f);
143+
m_props[i].prop_type = -1;
144+
Ref_Ptr_Release(m_props[i].render_obj);
145+
m_props[i].bounding_sphere.Center = Vector3(0.0f, 0.0f, 0.0f);
146+
m_props[i].bounding_sphere.Radius = 1.0f;
147+
m_propsUpdated = true;
148+
}
149+
}
150+
}
151+
152+
void W3DPropBuffer::Remove_Props_For_Construction(const Coord3D *position, const GeometryInfo &geometry, float angle)
153+
{
154+
for (int i = 0; i < m_numProps; i++) {
155+
if (m_props[i].render_obj != nullptr) {
156+
float radius = m_props[i].bounding_sphere.Radius;
157+
GeometryInfo geometry2(GEOMETRY_CYLINDER, false, 5.0f * radius, 2.0f * radius, 2.0f * radius);
158+
159+
if (g_thePartitionManager->Geom_Collides_With_Geom(
160+
position, geometry, angle, &m_props[i].position, geometry2, 0.0f)) {
161+
m_props[i].position.Set(0.0f, 0.0f, 0.0f);
162+
m_props[i].prop_type = -1;
163+
Ref_Ptr_Release(m_props[i].render_obj);
164+
m_props[i].bounding_sphere.Center = Vector3(0.0f, 0.0f, 0.0f);
165+
m_props[i].bounding_sphere.Radius = 1.0f;
166+
m_propsUpdated = true;
167+
}
168+
}
169+
}
170+
}
171+
172+
void W3DPropBuffer::Notify_Shroud_Changed()
173+
{
174+
for (int i = 0; i < m_numProps; i++) {
175+
m_props[i].shroud_status = g_thePartitionManager == nullptr ? SHROUDED_NONE : SHROUDED_INVALID;
176+
}
177+
}
178+
179+
void W3DPropBuffer::Draw_Props(RenderInfoClass &rinfo)
180+
{
181+
if (m_redoCull) {
182+
Cull(&rinfo.m_camera);
183+
}
184+
185+
GlobalData::TerrainLighting *lighting =
186+
g_theWriteableGlobalData->m_terrainObjectLighting[g_theWriteableGlobalData->m_timeOfDay];
187+
LightEnvironmentClass lightenv;
188+
Vector3 object_center(0.0f, 0.0f, 0.0f);
189+
Vector3 ambient(lighting[0].ambient.red, lighting[0].ambient.green, lighting[0].ambient.blue);
190+
lightenv.Reset(object_center, ambient);
191+
Matrix3D tm;
192+
Vector3 v(0.0f, 0.0f, 0.0f);
193+
Vector3 x(1.0f, 0.0f, 0.0f);
194+
Vector3 y(0.0f, 1.0f, 0.0f);
195+
196+
for (int i = 0; i < LIGHT_COUNT; i++) {
197+
m_light->Set_Ambient(v);
198+
m_light->Set_Diffuse(Vector3(lighting[i].diffuse.red, lighting[i].diffuse.green, lighting[i].diffuse.blue));
199+
m_light->Set_Specular(v);
200+
tm.Set(x, y, Vector3(lighting[i].lightPos.x, lighting[i].lightPos.y, lighting[i].lightPos.z), v);
201+
m_light->Set_Transform(tm);
202+
lightenv.Add_Light(*m_light);
203+
}
204+
205+
rinfo.m_lightEnvironment = &lightenv;
206+
207+
for (int i = 0; i < m_numProps; i++) {
208+
if (m_props[i].is_visible && m_props[i].render_obj != nullptr) {
209+
if (g_thePlayerList == nullptr || g_thePartitionManager == nullptr) {
210+
m_props[i].shroud_status = SHROUDED_NONE;
211+
}
212+
213+
if (m_props[i].shroud_status == SHROUDED_INVALID) {
214+
int index;
215+
216+
if (g_thePlayerList != nullptr) {
217+
index = g_thePlayerList->Get_Local_Player()->Get_Player_Index();
218+
} else {
219+
index = 0;
220+
}
221+
222+
m_props[i].shroud_status =
223+
g_thePartitionManager->Get_Prop_Shroud_Status_For_Player(index, &m_props[i].position);
224+
225+
if (m_props[i].shroud_status < SHROUDED_UNK4 && m_props[i].shroud_status > SHROUDED_INVALID) {
226+
if (g_theTerrainRenderObject->Get_Shroud() != nullptr && m_props[i].shroud_status != SHROUDED_INVALID) {
227+
rinfo.Push_Material_Pass(m_shroudMaterial);
228+
m_props[i].render_obj->Render(rinfo);
229+
rinfo.Pop_Material_Pass();
230+
} else {
231+
m_props[i].render_obj->Render(rinfo);
232+
}
233+
}
234+
}
235+
}
236+
}
237+
238+
rinfo.m_lightEnvironment = nullptr;
239+
}

0 commit comments

Comments
 (0)