Isle
Loading...
Searching...
No Matches
lego3dsound.cpp
Go to the documentation of this file.
1#include "lego3dsound.h"
2
3#include "legoactor.h"
5#include "legosoundmanager.h"
6#include "legovideomanager.h"
7#include "misc.h"
8#include "mxomni.h"
9
10#include <vec.h>
11
13
14// FUNCTION: LEGO1 0x10011630
16{
17 Init();
18}
19
20// FUNCTION: LEGO1 0x10011670
22{
23 Destroy();
24}
25
26// FUNCTION: LEGO1 0x10011680
28{
29 m_ds3dBuffer = NULL;
30 m_roi = NULL;
31 m_positionROI = NULL;
32 m_actor = NULL;
33 m_enabled = FALSE;
34 m_isActor = FALSE;
35 m_volume = 79;
36}
37
38// FUNCTION: LEGO1 0x100116a0
39// FUNCTION: BETA10 0x10039647
40MxResult Lego3DSound::Create(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char* p_name, MxS32 p_volume)
41{
42 m_volume = p_volume;
43
44 if (MxOmni::IsSound3D()) {
45 p_directSoundBuffer->QueryInterface(IID_IDirectSound3DBuffer, (LPVOID*) &m_ds3dBuffer);
46 if (m_ds3dBuffer == NULL) {
47 return FAILURE;
48 }
49
50 m_ds3dBuffer->SetMinDistance(15.0f, DS3D_IMMEDIATE);
51 m_ds3dBuffer->SetMaxDistance(100.0f, DS3D_IMMEDIATE);
52 m_ds3dBuffer->SetPosition(0.0f, 0.0f, -40.0f, DS3D_IMMEDIATE);
53 m_ds3dBuffer->SetConeOutsideVolume(-10000, DS3D_IMMEDIATE);
54 }
55
56 if (m_ds3dBuffer == NULL || p_name == NULL) {
57 return SUCCESS;
58 }
59
60 if (CharacterManager()->IsActor(p_name)) {
61 m_roi = CharacterManager()->GetActorROI(p_name, TRUE);
62 m_enabled = m_isActor = TRUE;
63 }
64 else {
65 m_roi = FindROI(p_name);
66 }
67
68 if (m_roi == NULL) {
69 m_roi = CharacterManager()->CreateAutoROI(NULL, p_name, TRUE);
70
71 if (m_roi != NULL) {
72 m_enabled = TRUE;
73 }
74 }
75
76 if (m_roi == NULL) {
77 return SUCCESS;
78 }
79
80 if (m_isActor) {
81 m_positionROI = m_roi->FindChildROI("head", m_roi);
82 }
83 else {
84 m_positionROI = m_roi;
85 }
86
87 if (MxOmni::IsSound3D()) {
88 const float* position = m_positionROI->GetWorldPosition();
89 m_ds3dBuffer->SetPosition(position[0], position[1], position[2], DS3D_IMMEDIATE);
90 }
91
92 LegoEntity* entity = m_roi->GetEntity();
93 if (entity != NULL && entity->IsA("LegoActor") && ((LegoActor*) entity)->GetSoundFrequencyFactor() != 0.0f) {
94 m_actor = ((LegoActor*) entity);
95 }
96
97 p_directSoundBuffer->GetFrequency(&m_dwFrequency);
98
99 if (m_actor != NULL) {
100 m_frequencyFactor = m_actor->GetSoundFrequencyFactor();
101
102 if (m_frequencyFactor != 0.0) {
103 p_directSoundBuffer->SetFrequency(m_frequencyFactor * m_dwFrequency);
104 }
105 }
106
107 return SUCCESS;
108}
109
110// FUNCTION: LEGO1 0x10011880
112{
113 if (m_ds3dBuffer) {
114 m_ds3dBuffer->Release();
115 m_ds3dBuffer = NULL;
116 }
117
118 if (m_enabled && m_roi && CharacterManager()) {
119 if (m_isActor) {
121 }
122 else {
124 }
125 }
126
127 Init();
128}
129
130// FUNCTION: LEGO1 0x100118e0
131// FUNCTION: BETA10 0x10039a2a
133{
134 MxU32 updated = FALSE;
135
136 if (m_positionROI != NULL) {
137 const float* position = m_positionROI->GetWorldPosition();
138
139 ViewROI* pov = VideoManager()->GetViewROI();
140 assert(pov);
141
142 const float* povPosition = pov->GetWorldPosition();
143 float distance = DISTSQRD3(povPosition, position);
144
145 if (distance > 10000.0f) {
146 return FALSE;
147 }
148
149 if (m_ds3dBuffer != NULL) {
150 m_ds3dBuffer->SetPosition(position[0], position[1], position[2], DS3D_IMMEDIATE);
151 }
152 else {
153 MxS32 newVolume = m_volume;
154 if (distance < 100.0f) {
155 newVolume = m_volume;
156 }
157 else if (distance < 400.0f) {
158 newVolume *= 0.4;
159 }
160 else if (distance < 3600.0f) {
161 newVolume *= 0.1;
162 }
163 else if (distance < 10000.0f) {
164 newVolume = 0;
165 }
166
167 newVolume = newVolume * SoundManager()->GetVolume() / 100;
168 newVolume = SoundManager()->GetAttenuation(newVolume);
169 p_directSoundBuffer->SetVolume(newVolume);
170 }
171
172 updated = TRUE;
173 }
174
175 if (m_actor != NULL) {
176 if (abs(m_frequencyFactor - m_actor->GetSoundFrequencyFactor()) > 0.0001) {
177 m_frequencyFactor = m_actor->GetSoundFrequencyFactor();
178 p_directSoundBuffer->SetFrequency(m_frequencyFactor * m_dwFrequency);
179 updated = TRUE;
180 }
181 }
182
183 return updated;
184}
185
186// FUNCTION: LEGO1 0x10011a60
187// FUNCTION: BETA10 0x10039d04
188void Lego3DSound::FUN_10011a60(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char* p_name)
189{
190 assert(p_directSoundBuffer);
191
192 if (p_name == NULL) {
193 if (m_ds3dBuffer != NULL) {
194 m_ds3dBuffer->SetMode(DS3DMODE_DISABLE, DS3D_IMMEDIATE);
195 }
196 }
197 else {
198 if (CharacterManager()->IsActor(p_name)) {
199 m_roi = CharacterManager()->GetActorROI(p_name, TRUE);
200 m_enabled = m_isActor = TRUE;
201 }
202 else {
203 m_roi = FindROI(p_name);
204 }
205
206 if (m_roi == NULL) {
207 m_roi = CharacterManager()->CreateAutoROI(NULL, p_name, TRUE);
208
209 if (m_roi != NULL) {
210 m_enabled = TRUE;
211 }
212 }
213
214 if (m_roi == NULL) {
215 return;
216 }
217
218 if (m_isActor) {
219 m_positionROI = m_roi->FindChildROI("head", m_roi);
220 }
221 else {
222 m_positionROI = m_roi;
223 }
224
225 if (m_ds3dBuffer != NULL) {
226 DWORD dwMode;
227 m_ds3dBuffer->GetMode(&dwMode);
228
229 if (dwMode & DS3DMODE_DISABLE) {
230 m_ds3dBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE);
231 }
232
233 const float* position = m_positionROI->GetWorldPosition();
234 m_ds3dBuffer->SetPosition(position[0], position[1], position[2], DS3D_IMMEDIATE);
235 }
236 else {
237 const float* position = m_positionROI->GetWorldPosition();
238 ViewROI* pov = VideoManager()->GetViewROI();
239
240 if (pov != NULL) {
241 const float* povPosition = pov->GetWorldPosition();
242 float distance = DISTSQRD3(povPosition, position);
243
244 MxS32 newVolume;
245 if (distance < 100.0f) {
246 newVolume = m_volume;
247 }
248 else if (distance < 400.0f) {
249 newVolume = m_volume * 0.4;
250 }
251 else if (distance < 3600.0f) {
252 newVolume = m_volume * 0.1;
253 }
254 else {
255 newVolume = 0;
256 }
257
258 newVolume = newVolume * SoundManager()->GetVolume() / 100;
259 newVolume = SoundManager()->GetAttenuation(newVolume);
260 p_directSoundBuffer->SetVolume(newVolume);
261 }
262 }
263
264 LegoEntity* entity = m_roi->GetEntity();
265 if (entity != NULL && entity->IsA("LegoActor") && ((LegoActor*) entity)->GetSoundFrequencyFactor() != 0.0f) {
266 m_actor = ((LegoActor*) entity);
267 }
268
269 p_directSoundBuffer->GetFrequency(&m_dwFrequency);
270
271 if (m_actor != NULL) {
272 m_frequencyFactor = m_actor->GetSoundFrequencyFactor();
273
274 if (m_frequencyFactor != 0.0) {
275 p_directSoundBuffer->SetFrequency(m_frequencyFactor * m_dwFrequency);
276 }
277 }
278 }
279}
280
281// FUNCTION: LEGO1 0x10011ca0
283{
284 if (m_enabled && m_roi && CharacterManager()) {
285 if (m_isActor) {
287 }
288 else {
290 }
291 }
292
293 m_roi = NULL;
294 m_positionROI = NULL;
295 m_actor = NULL;
296}
297
298// FUNCTION: LEGO1 0x10011cf0
299// FUNCTION: BETA10 0x10039fe0
301{
302 if (MxOmni::IsSound3D()) {
303 if (m_ds3dBuffer == NULL) {
304 return -1;
305 }
306
307 m_ds3dBuffer->SetMinDistance(p_min, DS3D_IMMEDIATE);
308 m_ds3dBuffer->SetMaxDistance(p_max, DS3D_IMMEDIATE);
309 return 0;
310 }
311
312 return 1;
313}
[AI] Implements 3D positional sound logic for LEGO Island using DirectSound 3D buffers.
Definition: lego3dsound.h:19
void Reset()
[AI] Releases any in-world/actor/ROI associations and resets member pointers.
MxS32 SetDistance(MxS32 p_min, MxS32 p_max)
[AI] Sets the minimum and maximum 3D sound effective distances if 3D sound is enabled.
MxU32 UpdatePosition(LPDIRECTSOUNDBUFFER p_directSoundBuffer)
[AI] Recalculates and updates the sound position on the underlying DirectSound 3D buffer or the volum...
void FUN_10011a60(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char *p_name)
[AI] Associates a new in-world object to this sound, updating its 3D position tracking and (if applic...
virtual ~Lego3DSound()
[AI] Destroys the Lego3DSound object and releases associated DirectSound buffers and object reference...
Definition: lego3dsound.cpp:21
void Destroy()
[AI] Cleans up and releases all resources (DirectSound 3D buffer, associated object references).
MxResult Create(LPDIRECTSOUNDBUFFER p_directSoundBuffer, const char *p_name, MxS32 p_volume)
[AI] Initializes 3D sound for a given DirectSound buffer and associates it with a named game object.
Definition: lego3dsound.cpp:40
void Init()
[AI] Initializes internal fields to their defaults. Used by constructor and destroy logic....
Definition: lego3dsound.cpp:27
[AI] Represents an actor (character) entity in the LEGO Island 3D world, providing specific actor log...
Definition: legoactor.h:12
virtual MxFloat GetSoundFrequencyFactor()
[AI] Returns the current frequency factor for the actor's sound.
Definition: legoactor.h:60
LegoROI * CreateAutoROI(const char *p_name, const char *p_lodName, MxBool p_createEntity)
[AI] Creates an "auto" ROI object with the given name, LOD name, and optional entity creation.
void ReleaseActor(const char *p_name)
[AI] Releases a character/ROI by name, decrementing its reference count and deleting if zero.
LegoROI * GetActorROI(const char *p_name, MxBool p_createEntity)
[AI] Returns a LegoROI for the given character name, creating and registering the actor if necessary.
void ReleaseAutoROI(LegoROI *p_roi)
[AI] Releases an "auto" ROI, used for dynamically created ROI objects by this manager.
[AI] Represents an entity that can be placed and managed in the LEGO Island world.
Definition: legoentity.h:16
MxBool IsA(const char *p_name) const override
[AI] Polymorphic type check for this entity given a string.
Definition: legoentity.h:59
LegoROI * FindChildROI(const LegoChar *p_name, LegoROI *p_roi)
[AI] Recursively searches for a child ROI by name, starting at the given ROI.
Definition: legoroi.cpp:349
LegoEntity * GetEntity()
[AI] Gets the entity associated with this ROI (or NULL).
Definition: legoroi.h:293
LegoROI * GetViewROI()
[AI] Returns the viewpoint ROI for the current view/camera.
virtual MxS32 GetVolume()
[AI] Gets the current global audio volume.
static MxBool IsSound3D()
[AI] Returns current state of 3D sound configuration.
Definition: mxomni.cpp:387
MxS32 GetAttenuation(MxU32 p_volume)
[AI] Maps a percentage volume (1-100) to a DirectSound-specific attenuation value.
const float * GetWorldPosition() const
Returns a pointer to the world position from the transformation matrix (translation row).
[AI] ViewROI objects represent viewable and placeable objects in the scene, each holding their own tr...
Definition: viewroi.h:13
LPSTR LPSTR LPVOID
Definition: d3dcaps.h:216
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
typedef DWORD(FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
struct IDirectSoundBuffer * LPDIRECTSOUNDBUFFER
Definition: dsound.h:47
#define DS3D_IMMEDIATE
Definition: dsound.h:777
#define DS3DMODE_DISABLE
Definition: dsound.h:775
#define DS3DMODE_NORMAL
Definition: dsound.h:773
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
LegoVideoManager * VideoManager()
[AI] Accessor for the game's LegoVideoManager subsystem. Used for managing 3D/video hardware....
Definition: misc.cpp:29
LegoCharacterManager * CharacterManager()
[AI] Accessor for the character manager, which manages in-game characters/NPCs. [AI]
Definition: misc.cpp:101
LegoSoundManager * SoundManager()
[AI] Accessor for the game's LegoSoundManager subsystem from the global LegoOmni instance....
Definition: misc.cpp:22
LegoROI * FindROI(const char *p_name)
[AI] Looks up a LegoROI (Real-time Object Instance) by name in the current world or global registry.
Definition: misc.cpp:151
MxLong MxResult
[AI]
Definition: mxtypes.h:106
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32
#define DISTSQRD3(v, w)
Definition: vec.h:478