mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-19 20:19:50 +02:00
Quake 4 integrated with DoomRTX
This commit is contained in:
@@ -0,0 +1,780 @@
|
||||
// BSE_Effect.cpp
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#include "BSE_Envelope.h"
|
||||
#include "BSE_Particle.h"
|
||||
#include "BSE.h"
|
||||
#include "BSE_SpawnDomains.h"
|
||||
|
||||
//#include "../renderer/RenderCommon.h"
|
||||
|
||||
static ID_INLINE void BSE_BoundTriSurf(srfTriangles_t* tri) {
|
||||
if (!tri) {
|
||||
return;
|
||||
}
|
||||
if (tri->numVerts <= 0 || !tri->verts) {
|
||||
tri->bounds.Clear();
|
||||
return;
|
||||
}
|
||||
tri->bounds.Clear();
|
||||
for (int i = 0; i < tri->numVerts; ++i) {
|
||||
tri->bounds.AddPoint(tri->verts[i].xyz);
|
||||
}
|
||||
}
|
||||
|
||||
void rvBSE::Init(const rvDeclEffect* declEffect, renderEffect_s* parms, float time)
|
||||
{
|
||||
int v6; // esi
|
||||
float* v7; // ecx
|
||||
float* v8; // eax
|
||||
double v9; // st3
|
||||
double v10; // st5
|
||||
float* v11; // esi
|
||||
float* v12; // eax
|
||||
int v13; // ecx
|
||||
double v14; // st5
|
||||
//float v15; // [esp+18h] [ebp-30h]
|
||||
//float v16; // [esp+1Ch] [ebp-2Ch]
|
||||
//float v17; // [esp+20h] [ebp-28h]
|
||||
//float v18; // [esp+24h] [ebp-24h]
|
||||
//float v19; // [esp+28h] [ebp-20h]
|
||||
//float v20; // [esp+2Ch] [ebp-1Ch]
|
||||
//float v21; // [esp+30h] [ebp-18h] BYREF
|
||||
//float v22[5]; // [esp+34h] [ebp-14h] BYREF
|
||||
float parmsa; // [esp+50h] [ebp+8h]
|
||||
|
||||
this->mStartTime = parms->startTime;
|
||||
this->mDeclEffect = declEffect;
|
||||
this->mLastTime = time;
|
||||
this->mFlags = 0;
|
||||
this->mDuration = 0.0;
|
||||
this->mAttenuation = 1.0;
|
||||
v6 = 2;
|
||||
this->mCost = 0.0;
|
||||
this->mFlags = parms->loop;
|
||||
this->mCurrentLocalBounds[1].z = 0.0;
|
||||
this->mCurrentLocalBounds[1].y = 0.0;
|
||||
v7 = &this->mLastRenderBounds[0].z;
|
||||
this->mCurrentLocalBounds[1].x = 0.0;
|
||||
this->mCurrentLocalBounds[0].z = 0.0;
|
||||
this->mCurrentLocalBounds[0].y = 0.0;
|
||||
this->mCurrentLocalBounds[0].x = 0.0;
|
||||
v8 = &this->mCurrentLocalBounds[0].z;
|
||||
v9 = declEffect->mSize;
|
||||
this->mCurrentLocalBounds[0].x = this->mCurrentLocalBounds[0].x - v9;
|
||||
this->mCurrentLocalBounds[0].y = this->mCurrentLocalBounds[0].y - v9;
|
||||
this->mCurrentLocalBounds[0].z = this->mCurrentLocalBounds[0].z - v9;
|
||||
this->mCurrentLocalBounds[1].x = this->mCurrentLocalBounds[1].x + v9;
|
||||
this->mCurrentLocalBounds[1].y = v9 + this->mCurrentLocalBounds[1].y;
|
||||
this->mCurrentLocalBounds[1].z = v9 + this->mCurrentLocalBounds[1].z;
|
||||
do
|
||||
{
|
||||
v10 = *(v8 - 2);
|
||||
v8 += 3;
|
||||
*(v7 - 2) = v10;
|
||||
v7 += 3;
|
||||
--v6;
|
||||
*(v7 - 4) = *(v8 - 4);
|
||||
*(v7 - 3) = *(v8 - 3);
|
||||
} while (v6);
|
||||
this->mGrownRenderBounds[0].z = 1.0e30;
|
||||
this->mGrownRenderBounds[0].y = 1.0e30;
|
||||
this->mGrownRenderBounds[0].x = 1.0e30;
|
||||
parmsa = -1.0e30;
|
||||
this->mGrownRenderBounds[1].z = parmsa;
|
||||
this->mGrownRenderBounds[1].y = parmsa;
|
||||
this->mGrownRenderBounds[1].x = parmsa;
|
||||
this->mForcePush = 0;
|
||||
this->mOriginalOrigin.x = parms->origin.x;
|
||||
this->mOriginalOrigin.y = parms->origin.y;
|
||||
this->mOriginalOrigin.z = parms->origin.z;
|
||||
this->mOriginalEndOrigin.z = 0.0;
|
||||
this->mOriginalEndOrigin.y = 0.0;
|
||||
this->mOriginalEndOrigin.x = 0.0;
|
||||
memcpy(&this->mOriginalAxis, &parms->axis, sizeof(this->mOriginalAxis));
|
||||
//v18 = this->mOriginalOrigin.x + this->mCurrentLocalBounds.b[1].x;
|
||||
//v19 = this->mCurrentLocalBounds[1].y + this->mOriginalOrigin.y;
|
||||
//v11 = &v21;
|
||||
//v20 = this->mCurrentLocalBounds[1].z + this->mOriginalOrigin.z;
|
||||
//v12 = &this->mCurrentWorldBounds[0].y;
|
||||
//v13 = 2;
|
||||
//v15 = this->mOriginalOrigin.x + this->mCurrentLocalBounds.b[0].x;
|
||||
//v16 = this->mCurrentLocalBounds[0].y + this->mOriginalOrigin.y;
|
||||
//v17 = this->mCurrentLocalBounds[0].z + this->mOriginalOrigin.z;
|
||||
//v21 = v15;
|
||||
//v22[0] = v16;
|
||||
//v22[1] = v17;
|
||||
//v22[2] = v18;
|
||||
//v22[3] = v19;
|
||||
//v22[4] = v20;
|
||||
//do
|
||||
//{
|
||||
// v14 = *v11;
|
||||
// v11 += 3;
|
||||
// *(v12 - 1) = v14;
|
||||
// v12 += 3;
|
||||
// --v13;
|
||||
// *(v12 - 3) = *(float*)((char*)v12 + (char*)&v21 - (char*)&this->mCurrentWorldBounds - 12);
|
||||
// *(v12 - 2) = *(float*)((char*)v12 + (char*)v22 - (char*)&this->mCurrentWorldBounds - 12);
|
||||
//} while (v13);
|
||||
if (parms->hasEndOrigin)
|
||||
{
|
||||
this->mFlags |= 2u;
|
||||
this->mOriginalEndOrigin.x = parms->endOrigin.x;
|
||||
this->mOriginalEndOrigin.y = parms->endOrigin.y;
|
||||
this->mOriginalEndOrigin.z = parms->endOrigin.z;
|
||||
this->mCurrentEndOrigin.x = parms->endOrigin.x;
|
||||
this->mCurrentEndOrigin.y = parms->endOrigin.y;
|
||||
this->mCurrentEndOrigin.z = parms->endOrigin.z;
|
||||
}
|
||||
this->mCurrentTime = time;
|
||||
this->mCurrentOrigin.x = this->mOriginalOrigin.x;
|
||||
this->mCurrentOrigin.y = this->mOriginalOrigin.y;
|
||||
this->mCurrentOrigin.z = this->mOriginalOrigin.z;
|
||||
this->mCurrentVelocity.z = 0.0;
|
||||
this->mCurrentVelocity.y = 0.0;
|
||||
this->mCurrentVelocity.x = 0.0;
|
||||
this->mCurrentWorldBounds.Clear();
|
||||
this->mCurrentWorldBounds.AddPoint(this->mCurrentOrigin + this->mCurrentLocalBounds[0]);
|
||||
this->mCurrentWorldBounds.AddPoint(this->mCurrentOrigin + this->mCurrentLocalBounds[1]);
|
||||
this->mSpriteSize.Zero();
|
||||
UpdateFromOwner(parms, time, 1);
|
||||
this->mReferenceSound = 0;
|
||||
if (parms->referenceSoundHandle > 0) {
|
||||
this->mReferenceSound = soundSystem->EmitterForIndex(SOUNDWORLD_GAME, parms->referenceSoundHandle);
|
||||
}
|
||||
UpdateSegments(time);
|
||||
this->mOriginDistanceToCamera = 0.0;
|
||||
this->mShortestDistanceToCamera = 0.0;
|
||||
}
|
||||
|
||||
float rvBSE::GetAttenuation(rvSegmentTemplate* st) const
|
||||
{
|
||||
double result; // st7
|
||||
float sta; // [esp+4h] [ebp+4h]
|
||||
float stb; // [esp+4h] [ebp+4h]
|
||||
float stc; // [esp+4h] [ebp+4h]
|
||||
float std; // [esp+4h] [ebp+4h]
|
||||
|
||||
result = 0.0;
|
||||
if (st->mAttenuation.x <= 0.0 && st->mAttenuation.y <= 0.0)
|
||||
return this->mAttenuation;
|
||||
sta = st->mAttenuation.x + 1.0;
|
||||
if (sta > (double)this->mShortestDistanceToCamera)
|
||||
return this->mAttenuation;
|
||||
stb = st->mAttenuation.y - 1.0;
|
||||
if (stb >= (double)this->mShortestDistanceToCamera)
|
||||
{
|
||||
stc = (this->mShortestDistanceToCamera - st->mAttenuation.x) / (st->mAttenuation.y - st->mAttenuation.x);
|
||||
std = (1.0 - stc) * this->mAttenuation;
|
||||
result = std;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float rvBSE::GetOriginAttenuation(rvSegmentTemplate* st) const
|
||||
{
|
||||
float result = 0.0f;
|
||||
|
||||
if (st->mAttenuation.x <= 0.0f && st->mAttenuation.y <= 0.0f) {
|
||||
return st->mScale * mAttenuation;
|
||||
}
|
||||
|
||||
if (st->mAttenuation.x + 1.0f > mOriginDistanceToCamera) {
|
||||
return st->mScale * mAttenuation;
|
||||
}
|
||||
|
||||
if (st->mAttenuation.y - 1.0f >= mOriginDistanceToCamera) {
|
||||
const float lerp = (mOriginDistanceToCamera - st->mAttenuation.x) / (st->mAttenuation.y - st->mAttenuation.x);
|
||||
result = (1.0f - lerp) * st->mScale * mAttenuation;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void rvBSE::UpdateSoundEmitter(rvSegmentTemplate* st, rvSegment* seg)
|
||||
{
|
||||
if (!st || !seg || !mReferenceSound) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetStopped()) {
|
||||
// Stop looping sounds when the owning effect is stopped.
|
||||
if (st->GetSoundLooping() && (seg->mFlags & 2) != 0) {
|
||||
mReferenceSound->StopSound(static_cast<s_channelType>(seg->mSegmentTemplateHandle + SCHANNEL_ONE));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
soundShaderParms_t parms = {};
|
||||
parms.volume = seg->mSoundVolume;
|
||||
parms.frequencyShift = seg->mFreqShift;
|
||||
|
||||
// Keep the emitter spatialized at the current effect origin so sound
|
||||
// tracks moving/attached effects correctly.
|
||||
mReferenceSound->UpdateEmitter(mCurrentOrigin, mCurrentVelocity, 0, &parms);
|
||||
}
|
||||
const idVec3 rvBSE::GetInterpolatedOffset(float time) const
|
||||
{
|
||||
idVec3 result; // eax
|
||||
float v5; // [esp+0h] [ebp-18h]
|
||||
float v6; // [esp+4h] [ebp-14h]
|
||||
float v7; // [esp+8h] [ebp-10h]
|
||||
float v8; // [esp+Ch] [ebp-Ch]
|
||||
float v9; // [esp+10h] [ebp-8h]
|
||||
float v10; // [esp+14h] [ebp-4h]
|
||||
float deltaTime; // [esp+1Ch] [ebp+4h]
|
||||
float deltaTimea; // [esp+1Ch] [ebp+4h]
|
||||
|
||||
result.z = 0.0;
|
||||
result.y = 0.0;
|
||||
result.x = 0.0;
|
||||
deltaTime = this->mCurrentTime - this->mLastTime;
|
||||
if (deltaTime >= 0.0020000001)
|
||||
{
|
||||
deltaTimea = 1.0 - (time - this->mLastTime) / deltaTime;
|
||||
v5 = this->mCurrentOrigin.x - this->mLastOrigin.x;
|
||||
v6 = this->mCurrentOrigin.y - this->mLastOrigin.y;
|
||||
v7 = this->mCurrentOrigin.z - this->mLastOrigin.z;
|
||||
v8 = v5 * deltaTimea;
|
||||
v9 = v6 * deltaTimea;
|
||||
v10 = deltaTimea * v7;
|
||||
result.x = v8;
|
||||
result.y = v9;
|
||||
result.z = v10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rvBSE::SetDuration(float time)
|
||||
{
|
||||
double v2; // st7
|
||||
|
||||
v2 = time;
|
||||
if (time < 0.0)
|
||||
{
|
||||
v2 = this->mDeclEffect->mMinDuration;
|
||||
LABEL_3:
|
||||
this->mDuration = v2;
|
||||
return;
|
||||
}
|
||||
if (this->mDuration < v2)
|
||||
goto LABEL_3;
|
||||
}
|
||||
|
||||
const char* rvBSE::GetDeclName()
|
||||
{
|
||||
return mDeclEffect->base->GetName();
|
||||
}
|
||||
|
||||
void rvBSE::UpdateAttenuation()
|
||||
{
|
||||
if ((this->mDeclEffect->mFlags & ETFLAG_ATTENUATES) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 viewOrigin;
|
||||
idMat3 viewAxis;
|
||||
game->GetPlayerView(viewOrigin, viewAxis);
|
||||
|
||||
const float originDistance = (mCurrentOrigin - viewOrigin).LengthFast();
|
||||
mOriginDistanceToCamera = idMath::ClampFloat(1.0f, 131072.0f, originDistance);
|
||||
|
||||
// Match vanilla BSE attenuation space conversion (uses current axis here).
|
||||
const idVec3 localView = mCurrentAxis * (viewOrigin - mCurrentOrigin);
|
||||
const float shortest = mCurrentLocalBounds.ShortestDistance(localView);
|
||||
mShortestDistanceToCamera = idMath::ClampFloat(1.0f, 131072.0f, shortest);
|
||||
}
|
||||
|
||||
void rvBSE::LoopInstant(float time)
|
||||
{
|
||||
rvBSE* v2; // esi
|
||||
int v3; // edi
|
||||
bool v4; // zf
|
||||
bool v5; // sf
|
||||
int v6; // ebx
|
||||
double v7; // st7
|
||||
|
||||
v2 = this;
|
||||
if (0.0 == this->mDuration)
|
||||
{
|
||||
v3 = 0;
|
||||
v4 = this->mSegments.Num() == 0;
|
||||
v5 = this->mSegments.Num() < 0;
|
||||
this->mStartTime = this->mDeclEffect->mMaxDuration + 0.5 + this->mStartTime;
|
||||
if (!v5 && !v4)
|
||||
{
|
||||
v6 = 0;
|
||||
do
|
||||
{
|
||||
v2->mSegments[v6].ResetTime(v2, v2->mStartTime);
|
||||
++v3;
|
||||
++v6;
|
||||
} while (v3 < v2->mSegments.Num());
|
||||
}
|
||||
if (bse_debug.GetInteger() == 2)
|
||||
{
|
||||
v7 = v2->mDeclEffect->mMaxDuration + 0.5;
|
||||
common->Printf("BSE: Looping duration %g\n", v7);
|
||||
}
|
||||
++v2->mDeclEffect->mLoopCount;
|
||||
}
|
||||
}
|
||||
|
||||
void rvBSE::LoopLooping(float time)
|
||||
{
|
||||
int v3; // edi
|
||||
bool v4; // cc
|
||||
int v5; // ebx
|
||||
|
||||
if (0.0 != this->mDuration)
|
||||
{
|
||||
v3 = 0;
|
||||
v4 = this->mSegments.Num() <= 0;
|
||||
this->mStartTime = this->mStartTime + this->mDuration;
|
||||
this->mDuration = 0.0;
|
||||
if (!v4)
|
||||
{
|
||||
v5 = 0;
|
||||
do
|
||||
{
|
||||
mSegments[v5].ResetTime(this, this->mStartTime);
|
||||
++v3;
|
||||
++v5;
|
||||
} while (v3 < this->mSegments.Num());
|
||||
}
|
||||
if (bse_debug.GetInteger() == 2) {
|
||||
common->Printf("BSE: Looping duration: %g", this->mDuration);
|
||||
}
|
||||
|
||||
++this->mDeclEffect->mLoopCount;
|
||||
}
|
||||
}
|
||||
bool rvBSE::Service(renderEffect_t* parms, float time, bool spawn, bool& forcePush)
|
||||
{
|
||||
renderEffect_s* v5; // ebp
|
||||
int v7; // edi
|
||||
int v8; // ebx
|
||||
int v9; // edi
|
||||
char v10; // bl
|
||||
int v11; // ebp
|
||||
bool v12; // zf
|
||||
float spawna; // [esp+24h] [ebp+Ch]
|
||||
float spawnb; // [esp+24h] [ebp+Ch]
|
||||
float spawnc; // [esp+24h] [ebp+Ch]
|
||||
float spawnd; // [esp+24h] [ebp+Ch]
|
||||
|
||||
v5 = parms;
|
||||
UpdateFromOwner(parms, time, 0);
|
||||
UpdateAttenuation();
|
||||
if (spawn)
|
||||
{
|
||||
v7 = 0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v8 = 0;
|
||||
do
|
||||
{
|
||||
spawna = 0.0f;
|
||||
mSegments[v8].Check(this, time, spawna);
|
||||
++v7;
|
||||
++v8;
|
||||
} while (v7 < this->mSegments.Num());
|
||||
}
|
||||
}
|
||||
if ((this->mFlags & 8) == 0 && parms->loop)
|
||||
{
|
||||
spawnb = this->mDuration + this->mStartTime;
|
||||
if (spawnb < (double)time)
|
||||
LoopLooping(time);
|
||||
}
|
||||
v9 = 0;
|
||||
v10 = 0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v11 = 0;
|
||||
do
|
||||
{
|
||||
if (mSegments[v11].UpdateParticles(this, time))
|
||||
v10 = 1;
|
||||
++v9;
|
||||
++v11;
|
||||
} while (v9 < this->mSegments.Num());
|
||||
v5 = parms;
|
||||
}
|
||||
this->mFlags &= 0xFFFFFFFB;
|
||||
forcePush = this->mForcePush;
|
||||
v12 = (this->mFlags & 8) == 0;
|
||||
this->mForcePush = 0;
|
||||
if (!v12)
|
||||
return v10 == 0;
|
||||
if (v5->loop)
|
||||
{
|
||||
spawnc = this->mDuration + this->mStartTime;
|
||||
if (spawnc < (double)time)
|
||||
LoopInstant(time);
|
||||
if (v5->loop)
|
||||
return 0;
|
||||
}
|
||||
spawnd = this->mDuration + this->mStartTime;
|
||||
return spawnd < (double)time;
|
||||
}
|
||||
|
||||
float rvBSE::EvaluateCost(int segment)
|
||||
{
|
||||
double result; // st7
|
||||
int v4; // edi
|
||||
int v5; // ebx
|
||||
double v6; // st7
|
||||
|
||||
if (segment < 0)
|
||||
{
|
||||
v4 = 0;
|
||||
this->mCost = 0.0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v5 = 0;
|
||||
do
|
||||
{
|
||||
v6 = mDeclEffect->EvaluateCost(
|
||||
this->mSegments[v5].mActiveCount,
|
||||
segment);
|
||||
++v4;
|
||||
++v5;
|
||||
this->mCost = v6 + this->mCost;
|
||||
} while (v4 < this->mSegments.Num());
|
||||
}
|
||||
result = this->mCost;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->mCost = mDeclEffect->EvaluateCost(
|
||||
this->mSegments[segment].mActiveCount,
|
||||
segment);
|
||||
result = this->mCost;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void rvBSE::InitModel(idRenderModel* model)
|
||||
{
|
||||
int v3; // edi
|
||||
int v4; // ebx
|
||||
|
||||
v3 = 0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v4 = 0;
|
||||
do
|
||||
{
|
||||
mSegments[v4].AllocateSurface(this, model);
|
||||
++v3;
|
||||
++v4;
|
||||
} while (v3 < this->mSegments.Num());
|
||||
}
|
||||
}
|
||||
|
||||
idRenderModel* rvBSE::Render(idRenderModel* model, const struct renderEffect_s* owner, const struct viewDef_s* view)
|
||||
{
|
||||
if (!bse_render.GetInteger() || !owner || !view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idRenderModelStatic* renderModel = dynamic_cast<idRenderModelStatic*>(model);
|
||||
if (model && !renderModel) {
|
||||
renderModelManager->FreeModel(model);
|
||||
model = NULL;
|
||||
}
|
||||
|
||||
if (!renderModel) {
|
||||
model = renderModelManager->AllocModel();
|
||||
renderModel = dynamic_cast<idRenderModelStatic*>(model);
|
||||
if (!renderModel) {
|
||||
if (model) {
|
||||
renderModelManager->FreeModel(model);
|
||||
}
|
||||
common->Warning("^4BSE:^1 Unable to allocate runtime model for effect '%s'", mDeclEffect ? mDeclEffect->GetName() : "<unknown>");
|
||||
return NULL;
|
||||
}
|
||||
renderModel->InitEmpty("_bse_runtime");
|
||||
InitModel(renderModel);
|
||||
}
|
||||
else {
|
||||
// Runtime particles mutate vertex/index data every frame.
|
||||
// Invalidate vertex/index caches so new data is uploaded.
|
||||
renderModel->FreeVertexCache();
|
||||
for (int i = 0; i < renderModel->NumSurfaces(); ++i) {
|
||||
const modelSurface_t* surf = renderModel->Surface(i);
|
||||
if (!surf || !surf->geometry) {
|
||||
continue;
|
||||
}
|
||||
srfTriangles_t* tri = surf->geometry;
|
||||
if (tri->indexCache) {
|
||||
tri->indexCache = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mViewAxis = view->renderView.viewaxis;
|
||||
mViewOrg = view->renderView.vieworg;
|
||||
|
||||
float time = view->floatTime;
|
||||
for (int i = 0; i < mSegments.Num(); ++i) {
|
||||
const bool active = mSegments[i].Active();
|
||||
|
||||
mSegments[i].ClearSurface(this, renderModel);
|
||||
if (active) {
|
||||
mSegments[i].Render(this, owner, renderModel, time);
|
||||
mSegments[i].RenderTrail(this, owner, renderModel, time);
|
||||
}
|
||||
}
|
||||
|
||||
// BSE runtime geometry is rebuilt every frame and includes strip-like particle
|
||||
// topology that can intentionally share points. Avoid full static-surface cleanup
|
||||
// here and only update per-surface/model bounds for culling.
|
||||
idBounds modelBounds;
|
||||
modelBounds.Clear();
|
||||
bool hasBounds = false;
|
||||
for (int i = 0; i < renderModel->NumSurfaces(); ++i) {
|
||||
const modelSurface_t* surf = renderModel->Surface(i);
|
||||
if (!surf || !surf->geometry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
srfTriangles_t* tri = surf->geometry;
|
||||
if (tri->numVerts <= 0 || tri->numIndexes <= 0) {
|
||||
tri->bounds.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
BSE_BoundTriSurf(tri);
|
||||
if (!hasBounds) {
|
||||
modelBounds = tri->bounds;
|
||||
hasBounds = true;
|
||||
}
|
||||
else {
|
||||
modelBounds.AddBounds(tri->bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasBounds) {
|
||||
modelBounds.Zero();
|
||||
}
|
||||
renderModel->bounds = modelBounds;
|
||||
DisplayDebugInfo(owner, view, renderModel->bounds);
|
||||
mLastRenderBounds = modelBounds;
|
||||
mGrownRenderBounds = mLastRenderBounds;
|
||||
mGrownRenderBounds.ExpandSelf(20.0f);
|
||||
mForcePush = true;
|
||||
return renderModel;
|
||||
}
|
||||
|
||||
void rvBSE::Destroy()
|
||||
{
|
||||
mSegments.Clear();
|
||||
mReferenceSound = NULL;
|
||||
}
|
||||
|
||||
|
||||
void rvBSE::UpdateSegments(float time)
|
||||
{
|
||||
int v3; // ebx
|
||||
rvSegment* v4; // eax
|
||||
rvParticle** v5; // esi
|
||||
bool v6; // cc
|
||||
int v7; // ecx
|
||||
int* v8; // eax
|
||||
rvSegment* v9; // esi
|
||||
rvSegment* v10; // ecx
|
||||
int v11; // edx
|
||||
int v12; // eax
|
||||
rvParticle** v13; // esi
|
||||
int v14; // esi
|
||||
int v15; // edi
|
||||
int v16; // esi
|
||||
int v17; // edi
|
||||
int v18; // esi
|
||||
int v19; // edi
|
||||
rvSegment* ptr; // [esp+14h] [ebp-14h]
|
||||
|
||||
v3 = this->mDeclEffect->mSegmentTemplates.Num();
|
||||
if (v3 > 0)
|
||||
{
|
||||
if (v3 != this->mSegments.Size())
|
||||
{
|
||||
mSegments.SetNum(v3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSegments.Clear();
|
||||
}
|
||||
v14 = 0;
|
||||
//this->mSegments.num = v3; // Not sure why this gets set twice? compiler optimization gone wrong?
|
||||
if (v3 > 0)
|
||||
{
|
||||
v15 = 0;
|
||||
do
|
||||
mSegments[v15++].Init(this, this->mDeclEffect, v14++, time);
|
||||
while (v14 < this->mSegments.Num());
|
||||
}
|
||||
v16 = 0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v17 = 0;
|
||||
do
|
||||
{
|
||||
mSegments[v17].CalcCounts(this, time);
|
||||
++v16;
|
||||
++v17;
|
||||
} while (v16 < this->mSegments.Num());
|
||||
}
|
||||
v18 = 0;
|
||||
if (this->mSegments.Num() > 0)
|
||||
{
|
||||
v19 = 0;
|
||||
do
|
||||
{
|
||||
|
||||
mSegments[v19].InitParticles(this);
|
||||
++v18;
|
||||
++v19;
|
||||
} while (v18 < this->mSegments.Num());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void rvBSE::DisplayDebugInfo(const struct renderEffect_s* parms, const struct viewDef_s* view, idBounds& bounds) {
|
||||
if (!parms || !view || !view->renderWorld) {
|
||||
return;
|
||||
}
|
||||
const int debugLevel = bse_debug.GetInteger();
|
||||
if (!debugLevel && !bse_showBounds.GetBool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
idRenderWorld* rw = view->renderWorld;
|
||||
|
||||
// Keep level-1 debug useful for logging without polluting gameplay visuals.
|
||||
// Level 2 enables heavy on-screen BSE overlays.
|
||||
if (debugLevel >= 2) {
|
||||
const char* effectName = "<unknown>";
|
||||
if (mDeclEffect && mDeclEffect->base) {
|
||||
effectName = mDeclEffect->base->GetName();
|
||||
}
|
||||
|
||||
idStr txt = va(
|
||||
"(%g) (size %g) (bri %g)\n%s",
|
||||
mCost,
|
||||
mDeclEffect ? mDeclEffect->mSize : 0.0f,
|
||||
parms->shaderParms[6],
|
||||
effectName);
|
||||
|
||||
rw->DebugAxis(parms->origin, parms->axis);
|
||||
rw->DrawText(txt.c_str(), parms->origin, 14.0f, colorCyan, view->renderView.viewaxis, 1, 0);
|
||||
}
|
||||
|
||||
if (!bse_showBounds.GetBool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
rw->DebugBounds(colorGreen, bounds, vec3_origin);
|
||||
|
||||
const idBox worldBox(mCurrentWorldBounds, parms->origin, parms->axis);
|
||||
rw->DebugBox(colorBlue, worldBox);
|
||||
|
||||
if (!mCurrentWorldBounds.Contains(bounds)) {
|
||||
rw->DebugBounds(colorRed, bounds, vec3_origin);
|
||||
}
|
||||
}
|
||||
|
||||
void rvBSE::UpdateFromOwner(renderEffect_s* parms, float time, bool init)
|
||||
{
|
||||
mLastTime = mCurrentTime;
|
||||
mLastOrigin = mCurrentOrigin;
|
||||
|
||||
mCurrentTime = time;
|
||||
mCurrentOrigin = parms->origin;
|
||||
mCurrentAxis = parms->axis;
|
||||
mCurrentAxisTransposed = mCurrentAxis.Transpose();
|
||||
|
||||
const float dt = mCurrentTime - mLastTime;
|
||||
if (dt > 0.002f) {
|
||||
mCurrentVelocity = (mCurrentOrigin - mLastOrigin) * (1.0f / dt);
|
||||
}
|
||||
// Vanilla keeps the last valid owner velocity when multiple updates land
|
||||
// on the same timestamp; avoid zeroing in that case.
|
||||
|
||||
mGravity = parms->gravity;
|
||||
mGravityDir = mGravity;
|
||||
const float gravityLengthSqr = mGravityDir.LengthSqr();
|
||||
if (gravityLengthSqr > 0.0f) {
|
||||
mGravityDir *= idMath::InvSqrt(gravityLengthSqr);
|
||||
}
|
||||
|
||||
SetLooping(parms->loop);
|
||||
SetHasEndOrigin(parms->hasEndOrigin);
|
||||
SetOrientateIdentity((mDeclEffect->mFlags & ETFLAG_ORIENTATE_IDENTITY) != 0);
|
||||
SetFlag(parms->ambient, EFLAG_AMBIENT);
|
||||
|
||||
const idVec3 halfSize(mDeclEffect->mSize, mDeclEffect->mSize, mDeclEffect->mSize);
|
||||
|
||||
mCurrentWorldBounds.AddPoint(mCurrentOrigin + halfSize);
|
||||
mCurrentWorldBounds.AddPoint(mCurrentOrigin - halfSize);
|
||||
|
||||
if (parms->hasEndOrigin && (mDeclEffect->mFlags & ETFLAG_USES_ENDORIGIN) != 0) {
|
||||
const bool endOriginChanged = init || parms->endOrigin != mCurrentEndOrigin || mCurrentOrigin != mLastOrigin;
|
||||
mCurrentEndOrigin = parms->endOrigin;
|
||||
mCurrentWorldBounds.AddPoint(mCurrentEndOrigin + halfSize);
|
||||
mCurrentWorldBounds.AddPoint(mCurrentEndOrigin - halfSize);
|
||||
SetEndOriginChanged(endOriginChanged);
|
||||
}
|
||||
else {
|
||||
mCurrentEndOrigin = parms->endOrigin;
|
||||
SetEndOriginChanged(false);
|
||||
}
|
||||
|
||||
mCurrentLocalBounds.Clear();
|
||||
for (int ix = 0; ix < 2; ++ix) {
|
||||
for (int iy = 0; iy < 2; ++iy) {
|
||||
for (int iz = 0; iz < 2; ++iz) {
|
||||
const idVec3 corner(
|
||||
mCurrentWorldBounds[ix].x,
|
||||
mCurrentWorldBounds[iy].y,
|
||||
mCurrentWorldBounds[iz].z);
|
||||
const idVec3 local = mCurrentAxisTransposed * (corner - mCurrentOrigin);
|
||||
mCurrentLocalBounds.AddPoint(local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mLightningAxis = mCurrentAxis;
|
||||
if (GetHasEndOrigin()) {
|
||||
idVec3 forward = mCurrentEndOrigin - mCurrentOrigin;
|
||||
if (forward.Normalize() > BSE_TIME_EPSILON) {
|
||||
idVec3 up = mCurrentAxis[2];
|
||||
if (idMath::Fabs(forward * up) > 0.98f) {
|
||||
up = mCurrentAxis[1];
|
||||
}
|
||||
|
||||
idVec3 right = up.Cross(forward);
|
||||
if (right.Normalize() > BSE_TIME_EPSILON) {
|
||||
up = forward.Cross(right);
|
||||
up.Normalize();
|
||||
mLightningAxis[0] = forward;
|
||||
mLightningAxis[1] = right;
|
||||
mLightningAxis[2] = up;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentWindVector.Zero();
|
||||
memcpy( mShaderParms, parms->shaderParms, sizeof( mShaderParms ) );
|
||||
mTint.Set(parms->shaderParms[0], parms->shaderParms[1], parms->shaderParms[2], parms->shaderParms[3]);
|
||||
mBrightness = parms->shaderParms[6];
|
||||
mSpriteSize.x = parms->shaderParms[8];
|
||||
mSpriteSize.y = parms->shaderParms[9];
|
||||
mAttenuation = parms->attenuation;
|
||||
mSuppressLightsInViewID = parms->suppressSurfaceInViewID;
|
||||
}
|
||||
Reference in New Issue
Block a user