view ParticleEngine.cpp @ 16:5a95b9ed31f3

13.10.12
author Lower
date Sat, 13 Oct 2012 20:25:41 +0600
parents 8b8875f5b359
children bcc051713d20
line wrap: on
line source

#include "ParticleEngine.h"
#include "Time.h"
#include "Render.h"
#include "Viewport.h"
#include "Outdoor.h"
#include "Game.h"
#include "IndoorCamera.h"
#include "Math.h"
#include "LOD.h"
#include "stru346.h"

#include "mm7_data.h"

//----- (0048AAC5) --------------------------------------------------------
ParticleEngine::ParticleEngine()
{
  for (uint i = 0; i < 500; ++i)
    memset(&pParticles[i], 0, sizeof(pParticles[i]));

  ResetParticles();
}

//----- (0048AAF6) --------------------------------------------------------
void ParticleEngine::ResetParticles()
{
  memset(pParticles, 0, 500 * sizeof(*pParticles));
  uStartParticle = 500;
  uEndParticle = 0;
  uTimeElapsed = 0;
}

//----- (0048AB23) --------------------------------------------------------
void ParticleEngine::AddParticle(Particle_ *a2)
{
  signed int v2; // eax@2
  Particle *v3; // edx@2
  Particle *v4; // esi@10
  int v5; // ecx@10
  char v6; // zf@10

  if ( !pMiscTimer->bPaused )
  {
    v2 = 0;
    v3 = (Particle *)this;
    do
    {
      if ( !v3->bFree )
        break;
      ++v2;
      ++v3;
    }
    while ( v2 < 500 );
    if ( v2 < 500 )
    {
      if ( v2 < this->uStartParticle )
        this->uStartParticle = v2;
      if ( v2 > this->uEndParticle )
        this->uEndParticle = v2;
      v4 = &this->pParticles[v2];
      v4->bFree = a2->bFree;
      v4->x = a2->x;
      v4->y = a2->y;
      v4->z = a2->z;
      v4->_x = a2->x;
      v4->_y = a2->y;
      v4->_z = a2->z;
      v4->flt_10 = a2->flt_10;
      v4->flt_14 = a2->flt_14;
      v4->flt_18 = a2->flt_18;
      v5 = a2->uDiffuse;
      v4->uParticleColor = v5;
      v4->uLightColor = v5;
      v6 = (v4->bFree & 4) == 0;
      v4->field_20 = a2->field_20;
      v4->uTextureID = a2->uTextureID;
      v4->flt_28 = a2->flt_28;
      if ( v6 )
      {
        v4->field_38 = 0;
        v4->_rotation = 0;
      }
      else
      {
        v4->field_38 = (unsigned __int8)rand() - 128;
        v4->_rotation = rand();
      }
    }
  }
}

//----- (0048ABF3) --------------------------------------------------------
void ParticleEngine::Draw()
{
  ParticleEngine *v1; // esi@1

  v1 = this;
  v1->uTimeElapsed += pEventTimer->uTimeElapsed;
  this->pLines.uNumLines = 0;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    DrawParticles_BLV();
  else
    DrawParticles_ODM();
  if ( pRenderer->pRenderD3D )
  {
    if ( v1->pLines.uNumLines )
    {
      pRenderer->pRenderD3D->pDevice->SetTexture(0, 0);
      pRenderer->pRenderD3D->pDevice->DrawPrimitive(
        D3DPT_LINELIST,
        452,
        v1->pLines.pLineVertices,
        v1->pLines.uNumLines,
        16);
    }
  }
}

//----- (0048AC65) --------------------------------------------------------
int ParticleEngine::UpdateParticles()
{
  ParticleEngine *v1; // ebx@1
  unsigned int time; // edi@1
  int v3; // eax@1
  int v4; // esi@2
  int v5; // eax@3
  char v6; // sf@4
  float v7; // ST4C_4@11
  double v8; // st7@12
  int v9; // eax@12
  double v10; // st7@14
  float v11; // ST4C_4@14
  float v12; // ST3C_4@14
  double v13; // ST20_8@14
  float v14; // ST3C_4@14
  double v15; // ST18_8@14
  float v16; // ST3C_4@14
  double v17; // ST10_8@14
  signed int result; // eax@19
  signed int v19; // [sp+38h] [bp-14h]@1
  int v20; // [sp+3Ch] [bp-10h]@1
  unsigned int time_; // [sp+40h] [bp-Ch]@1
  int v22; // [sp+44h] [bp-8h]@12
  int v23; // [sp+48h] [bp-4h]@1

  v20 = 0;
  v1 = this;
  time = pMiscTimer->bPaused == 0 ? pEventTimer->uTimeElapsed : 0;
  v3 = this->uStartParticle;
  v19 = 500;
  time_ = pMiscTimer->bPaused == 0 ? pEventTimer->uTimeElapsed : 0;
  v23 = this->uStartParticle;
  if ( v3 <= this->uEndParticle )
  {
    v4 = (int)((char *)&this->pParticles[v3].uParticleColor + 1);
    do
    {
      v5 = *(int *)(v4 - 0x1D);
      if ( v5 )
      {
        v6 = ((*(int *)(v4 + 3) - time) & 0x80000000u) != 0;
        *(int *)(v4 + 3) -= time;
        if ( v6 )
        {
          *(int *)(v4 - 0x1D) = 0;
        }
        else
        {
          if ( BYTE1(v5) & 2 )
          {
            *(int *)(v4 + 15) = *(int *)(v4 - 25);
            *(int *)(v4 + 19) = *(int *)(v4 - 21);
            *(int *)(v4 + 23) = *(int *)(v4 - 17);
          }
          if ( v5 & 1 )
            *(float *)(v4 - 5) = *(float *)(v4 - 5) - (double)(signed int)time_ * 5.0;
          if ( v5 & 8 )
          {
            v7 = (double)(signed int)time_;
            *(float *)(v4 - 25) = (double)(rand() % 5 - 2) * v7 * 0.0625 + *(float *)(v4 - 25);
            *(float *)(v4 - 21) = (double)(rand() % 5 - 2) * v7 * 0.0625 + *(float *)(v4 - 21);
            *(float *)(v4 - 17) = (double)(rand() % 5 + 4) * v7 * 0.0625 + *(float *)(v4 - 17);
          }
          v8 = (double)(signed int)time_ * 0.0078125;
          v9 = (signed int)(time * *(int *)(v4 + 27)) / 16;
          *(float *)(v4 - 25) = v8 * *(float *)(v4 - 13) + *(float *)(v4 - 25);
          *(float *)(v4 - 21) = v8 * *(float *)(v4 - 9) + *(float *)(v4 - 21);
          *(float *)(v4 - 17) = v8 * *(float *)(v4 - 5) + *(float *)(v4 - 17);
          *(int *)(v4 + 31) += v9;
          v22 = 2 * *(int *)(v4 + 3);
          if ( 2 * *(int *)(v4 + 3) >= 255 )
            v22 = 255;
          v10 = (double)v22 * 0.0039215689;
          v11 = v10;
          v12 = (double)*(char *)(v4 + 1) * v10;
          v13 = v12 + 6.7553994e15;
          v14 = (double)*(char *)v4 * v11;
          v15 = v14 + 6.7553994e15;
          v16 = (double)(*(int *)(v4 - 1) & 0xFF) * v11;
          v17 = v16 + 6.7553994e15;
          *(int *)(v4 + 71) = LODWORD(v17) | ((LODWORD(v15) | (LODWORD(v13) << 8)) << 8);
          if ( v23 < v19 )
            v19 = v23;
          if ( v23 > v20 )
            v20 = v23;
        }
      }
      ++v23;
      v4 += 104;
    }
    while ( v23 <= v1->uEndParticle );
  }
  v1->uEndParticle = v20;
  result = v19;
  v1->uStartParticle = v19;
  return result;
}

//----- (0048AE74) --------------------------------------------------------
bool ParticleEngine::ViewProject_TrueIfStillVisible(unsigned int uParticleID)
{
  Particle *pParticle; // esi@1
  double v56; // ST28_8@2
  float v4; // eax@4
  double v5; // ST34_8@4
  signed __int64 v6; // qtt@4
  double v7; // st7@4
  float v8; // ST18_4@4
  int v9; // ecx@4
  int v10; // eax@4
  double v11; // ST44_8@7
  double v12; // ST4C_8@7
  double v13; // ST4C_8@7
  int v14; // ecx@7
  signed __int64 v15; // qtt@7
  int v16; // eax@7
  int v17; // edx@7
  float v18; // edx@7
  int v19; // eax@7
  int v20; // edx@7
  int v21; // ST50_4@8
  int v22; // ebx@8
  int v23; // ecx@10
  int v24; // edi@10
  double v25; // ST44_8@12
  double v26; // ST4C_8@12
  int v27; // edi@12
  int v28; // ST40_4@12
  int v29; // ecx@12
  signed __int64 v30; // qtt@12
  int v31; // eax@12
  int v32; // edx@12
  float v33; // edx@12
  int v34; // eax@12
  int v35; // ecx@12
  int v36; // ST38_4@13
  int v37; // ST30_4@15
  int v38; // eax@16
  signed __int64 v40; // qtt@18
  int v41; // eax@18
  int v42; // ecx@18
  int v43; // eax@18
  unsigned __int64 v44; // qax@18
  double v45; // st7@18
  int v46; // ecx@18
  float v47; // ST18_4@18
  unsigned __int64 v48; // qax@18
  double y_int_; // [sp+10h] [bp-40h]@2
  int a2; // [sp+18h] [bp-38h]@10
  int x_int; // [sp+20h] [bp-30h]@2
  double z_int_; // [sp+24h] [bp-2Ch]@2
  int z_int_4; // [sp+28h] [bp-28h]@8
  int z; // [sp+3Ch] [bp-14h]@3
  double a5; // [sp+40h] [bp-10h]@4
  int a6; // [sp+48h] [bp-8h]@4
  int y; // [sp+4Ch] [bp-4h]@3

  pParticle = &this->pParticles[uParticleID];
  if ( !pParticle->bFree )
    return 0;
  uParticleID = LODWORD(pParticle->x);
  v56 = *(float *)&uParticleID + 6.7553994e15;
  x_int = LODWORD(v56);
  uParticleID = LODWORD(pParticle->y);
  y_int_ = *(float *)&uParticleID + 6.7553994e15;
  uParticleID = LODWORD(pParticle->z);
  z_int_ = *(float *)&uParticleID + 6.7553994e15;
  if ( !pRenderer->pRenderD3D )
  {
    if ( pBLVRenderParams->sPartyRotX )
    {
      if ( BYTE1(pParticle->bFree) & 2 )
      {
        v11 = pParticle->_x + 6.7553994e15;
        uParticleID = (LODWORD(v11) - pBLVRenderParams->vPartyPos.x) << 16;
        v12 = pParticle->_y + 6.7553994e15;
        y = (LODWORD(v12) - pBLVRenderParams->vPartyPos.y) << 16;
        z = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
        HIDWORD(a5) = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
                    - z;
        a6 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
        v13 = pParticle->_z + 6.7553994e15;
        uParticleID = (LODWORD(v13) - pBLVRenderParams->vPartyPos.z) << 16;
        z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
          - ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
        v14 = z;
        HIDWORD(v13) = (unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
        HIDWORD(a5) = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16;
        LODWORD(v15) = pBLVRenderParams->field_40 << 16;
        HIDWORD(v15) = pBLVRenderParams->field_40 >> 16;
        v16 = v15 / z;
        v17 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
        pParticle->field_58 = v16;
        uParticleID = (unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16;
        LODWORD(v18) = pBLVRenderParams->uViewportCenterX
                     - ((signed int)((unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16) >> 16);
        v19 = pParticle->field_58;
        pParticle->field_48 = v18;
        uParticleID = (unsigned __int64)(v19 * (signed __int64)(HIDWORD(v13) + HIDWORD(a5))) >> 16;
        v20 = pBLVRenderParams->uViewportCenterY
            - ((signed int)((unsigned __int64)(v19 * (signed __int64)(HIDWORD(v13) + HIDWORD(a5))) >> 16) >> 16);
        pParticle->field_54 = v14;
        pParticle->field_4C = v20;
      }
      uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
      y = (LODWORD(y_int_) - pBLVRenderParams->vPartyPos.y) << 16;
      HIDWORD(a5) = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
                  - ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
      a6 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
      HIDWORD(z_int_) = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
      uParticleID = (LODWORD(z_int_) - pBLVRenderParams->vPartyPos.z) << 16;
      v21 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
      v22 = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
      z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
      if ( v22 < (signed int)0x40000u || v22 > (signed int)0x1F400000u )
        return 0;
      v23 = a6 + z_int_4;
      a2 = a6 + z_int_4;
      v24 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
          + ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
    }
    else
    {
      if ( BYTE1(pParticle->bFree) & 2 )
      {
        v25 = pParticle->_x + 6.7553994e15;
        uParticleID = (LODWORD(v25) - pBLVRenderParams->vPartyPos.x) << 16;
        v26 = pParticle->_y + 6.7553994e15;
        y = (LODWORD(v26) - pBLVRenderParams->vPartyPos.y) << 16;
        HIDWORD(v25) = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
        v27 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
            - HIDWORD(v25);
        z = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
          - HIDWORD(v25);
        v28 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
        a5 = pParticle->_z + 6.7553994e15;
        v29 = (LODWORD(a5) - pBLVRenderParams->vPartyPos.z) << 16;
        LODWORD(v30) = pBLVRenderParams->field_40 << 16;
        HIDWORD(v30) = pBLVRenderParams->field_40 >> 16;
        v31 = v30 / z;
        v32 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
        pParticle->field_58 = v31;
        uParticleID = (unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16;
        LODWORD(v33) = pBLVRenderParams->uViewportCenterX
                     - ((signed int)((unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16) >> 16);
        v34 = pParticle->field_58;
        pParticle->field_48 = v33;
        v35 = pBLVRenderParams->uViewportCenterY
            - ((signed int)((unsigned __int64)(v34 * (signed __int64)v29) >> 16) >> 16);
        pParticle->field_54 = v27;
        pParticle->field_4C = v35;
      }
      uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
      y = (LODWORD(y_int_) - pBLVRenderParams->vPartyPos.y) << 16;
      v36 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
      v22 = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
      z = ((unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
      if ( v22 < 262144 || v22 > 524288000 )
        return 0;
      v37 = (unsigned __int64)((signed int)uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
      uParticleID = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
      v23 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
      a2 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
      v24 = (LODWORD(z_int_) - pBLVRenderParams->vPartyPos.z) << 16;
    }
    uParticleID = abs(v23);
    v38 = abs(v22);
    if ( v38 >= (signed int)uParticleID )
    {
      LODWORD(v40) = pBLVRenderParams->field_40 << 16;
      HIDWORD(v40) = pBLVRenderParams->field_40 >> 16;
      v41 = v40 / z;
      pParticle->field_58 = v41;
      uParticleID = (unsigned __int64)(v41 * (signed __int64)a2) >> 16;
      v42 = pBLVRenderParams->uViewportCenterX - ((signed int)((unsigned __int64)(v41 * (signed __int64)a2) >> 16) >> 16);
      v43 = pParticle->field_58;
      pParticle->uScreenSpaceX = v42;
      v44 = v43 * (signed __int64)v24;
      uParticleID = v44 >> 16;
      v45 = pParticle->flt_28;
      LODWORD(v44) = (signed int)(v44 >> 16) >> 16;
      v46 = pBLVRenderParams->uViewportCenterY - v44;
      pParticle->uScreenSpaceY = pBLVRenderParams->uViewportCenterY - v44;
      v47 = v45;
      v48 = _48B561_mess_with_scaling_along_z(/*v46, */v47) * (signed __int64)pParticle->field_58;
      uParticleID = v48 >> 16;
      pParticle->field_58 = v48 >> 16;
      v10 = z;
      goto LABEL_19;
    }
    return 0;
  }
  if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
          x_int,
          SLODWORD(y_int_),
          COERCE_UNSIGNED_INT64(*(float *)&uParticleID + 6.7553994e15),
          (signed int *)&uParticleID,
          &y,
          &z,
          1) )
    return 0;
  pGame->pIndoorCameraD3D->Project(uParticleID, y, z, (int *)&a5 + 1, &a6);
  pParticle->flt_5C = pGame->pIndoorCameraD3D->flt_D0;
  v4 = pParticle->flt_5C;
  pParticle->flt_60 = pGame->pIndoorCameraD3D->flt_D4;
  v5 = v4 + 6.7553994e15;
  LODWORD(v6) = 0;
  HIDWORD(v6) = SLOWORD(v5);
  v7 = pParticle->flt_28;
  pParticle->field_58 = v6 / (signed int)uParticleID;
  v8 = v7;
  pParticle->uScreenSpaceX = HIDWORD(a5);
  pParticle->uScreenSpaceY = a6;
  pParticle->field_58 = (unsigned __int64)(_48B561_mess_with_scaling_along_z(/*v9, */v8) * (signed __int64)pParticle->field_58) >> 16;
  v10 = uParticleID;
LABEL_19:
  pParticle->field_50 = v10;
  return 1;
}




//----- (0048B5B3) --------------------------------------------------------
bool ParticleEngine::_48B5B3(unsigned int uID)
{
  ParticleEngine *v2; // ST18_4@1
  int v3; // ebx@1
  int v4; // edi@1
  int v5; // ecx@1
  Particle *v6; // esi@1
  double v7; // ST14_8@2
  double v8; // ST34_8@4
  double v9; // ST3C_8@4
  int v10; // ST50_4@4
  int v11; // ST44_4@4
  double v12; // ST48_8@4
  signed __int64 v13; // qtt@4
  int v14; // eax@4
  int v15; // ST28_4@4
  int v16; // edi@6
  int v17; // eax@6
  double v18; // ST2C_8@8
  double v19; // ST34_8@8
  int v20; // ST50_4@8
  double v21; // ST34_8@8
  signed __int64 v22; // qtt@8
  int v23; // eax@8
  int v24; // ST28_4@8
  int v25; // edx@8
  int v26; // edx@9
  int v27; // eax@9
  int v28; // ebx@12
  signed __int64 v29; // qtt@13
  int v30; // eax@13
  int v31; // ST1C_4@13
  double v32; // st7@13
  signed int v33; // eax@13
  int v34; // ecx@13
  float v35; // ST04_4@13
  int v36; // eax@13
  int v37; // esi@15
  double v39; // [sp+10h] [bp-40h]@2
  int v40; // [sp+14h] [bp-3Ch]@12
  int v41; // [sp+1Ch] [bp-34h]@2
  double v42; // [sp+20h] [bp-30h]@2
  int v43; // [sp+24h] [bp-2Ch]@5
  int v44; // [sp+2Ch] [bp-24h]@1
  int v45; // [sp+40h] [bp-10h]@5
  int X_4; // [sp+48h] [bp-8h]@5
  int v47; // [sp+4Ch] [bp-4h]@5
  int v48; // [sp+4Ch] [bp-4h]@9
  int uIDc; // [sp+58h] [bp+8h]@4
  int uIDd; // [sp+58h] [bp+8h]@4
  int uIDe; // [sp+58h] [bp+8h]@5
  int uIDa; // [sp+58h] [bp+8h]@5
  int uIDf; // [sp+58h] [bp+8h]@8
  int uIDb; // [sp+58h] [bp+8h]@9

  v2 = this;
  v3 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX);
  v44 = stru_5C6E00->SinCos(pIndoorCamera->sRotationX - stru_5C6E00->uIntegerHalfPi);
  v4 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY);
  v5 = stru_5C6E00->SinCos(pIndoorCamera->sRotationY - stru_5C6E00->uIntegerHalfPi);
  v6 = &v2->pParticles[uID];
  if ( v6->bFree )
  {
    v7 = v6->x + 6.7553994e15;
    v41 = LODWORD(v7);
    v39 = v6->y + 6.7553994e15;
    v42 = v6->z + 6.7553994e15;
    if ( v3 )
    {
      if ( BYTE1(v6->bFree) & 2 )
      {
        v8 = v6->_x + 6.7553994e15;
        uIDc = (LODWORD(v8) - pIndoorCamera->pos.x) << 16;
        v9 = v6->_y + 6.7553994e15;
        v10 = (LODWORD(v9) - pIndoorCamera->pos.y) << 16;
        v11 = ((unsigned __int64)(uIDc * (signed __int64)v4) >> 16)
            + ((unsigned __int64)(v10 * (signed __int64)v5) >> 16);
        HIDWORD(v8) = (unsigned __int64)(uIDc * (signed __int64)v5) >> 16;
        v12 = v6->_z + 6.7553994e15;
        uIDd = (LODWORD(v12) - pIndoorCamera->pos.z) << 16;
        HIDWORD(v12) = ((unsigned __int64)(v11 * (signed __int64)v3) >> 16)
                     + ((unsigned __int64)(uIDd * (signed __int64)v44) >> 16);
        LODWORD(v13) = 0;
        HIDWORD(v13) = SLOWORD(pOutdoorCamera->int_fov_rad);
        v14 = v13 / SHIDWORD(v12);
        v6->field_58 = v14;
        v15 = v6->field_58;
        v6->uScreenSpaceX = pViewport->uScreenCenterX
                          - ((signed int)((unsigned __int64)(v14
                                                           * (signed __int64)(signed int)(((unsigned __int64)(v10 * (signed __int64)v4) >> 16)
                                                                                        - HIDWORD(v8))) >> 16) >> 16);
        v6->uScreenSpaceY = pViewport->uScreenCenterY
                          - ((signed int)((unsigned __int64)(v15
                                                           * (signed __int64)(signed int)(((unsigned __int64)(uIDd * (signed __int64)v3) >> 16)
                                                                                        - ((unsigned __int64)(v11 * (signed __int64)v44) >> 16))) >> 16) >> 16);
        v6->field_50 = HIDWORD(v12);
      }
      uIDe = (v41 - pIndoorCamera->pos.x) << 16;
      v47 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
      v45 = ((unsigned __int64)(uIDe * (signed __int64)v4) >> 16) + ((unsigned __int64)(v47 * (signed __int64)v5) >> 16);
      HIDWORD(v42) = (unsigned __int64)(uIDe * (signed __int64)v5) >> 16;
      uIDa = (LODWORD(v42) - pIndoorCamera->pos.z) << 16;
      X_4 = ((unsigned __int64)(uIDa * (signed __int64)v44) >> 16)
          + ((unsigned __int64)(v45 * (signed __int64)v3) >> 16);
      if ( X_4 < 262144 )
        return 0;
      v16 = ((unsigned __int64)(v47 * (signed __int64)v4) >> 16) - v43;
      v17 = ((unsigned __int64)(uIDa * (signed __int64)v3) >> 16)
          - ((unsigned __int64)(v45 * (signed __int64)v44) >> 16);
    }
    else
    {
      if ( BYTE1(v6->bFree) & 2 )
      {
        v18 = v6->_x + 6.7553994e15;
        uIDf = (LODWORD(v18) - pIndoorCamera->pos.x) << 16;
        v19 = v6->_y + 6.7553994e15;
        v20 = (LODWORD(v19) - pIndoorCamera->pos.y) << 16;
        v21 = v6->_z + 6.7553994e15;
        LODWORD(v22) = 0;
        HIDWORD(v22) = SLOWORD(pOutdoorCamera->int_fov_rad);
        v23 = v22
            / (signed int)(((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
                         + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16));
        v6->field_58 = v23;
        v24 = v6->field_58;
        v6->uScreenSpaceX = pViewport->uScreenCenterX
                          - ((signed int)((unsigned __int64)(v23
                                                           * (signed __int64)(signed int)(((unsigned __int64)(v20 * (signed __int64)v4) >> 16)
                                                                                        - ((unsigned __int64)(uIDf * (signed __int64)v5) >> 16))) >> 16) >> 16);
        v25 = pViewport->uScreenCenterY
            - ((signed int)((unsigned __int64)(v24 * (signed __int64)SLODWORD(v21)) >> 16) >> 16);
        v6->field_50 = ((unsigned __int64)(v20 * (signed __int64)v5) >> 16)
                     + ((unsigned __int64)(uIDf * (signed __int64)v4) >> 16);
        v6->uScreenSpaceY = v25;
      }
      uIDb = (v41 - pIndoorCamera->pos.x) << 16;
      v48 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
      v26 = (unsigned __int64)(v48 * (signed __int64)v5) >> 16;
      v27 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
      X_4 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
      if ( v27 < 262144 || v27 > (pOutdoorCamera->uPickDepth - 1000) << 16 )
        return 0;
      v17 = LODWORD(v42);
      v16 = ((unsigned __int64)(v48 * (signed __int64)v4) >> 16) - ((unsigned __int64)(uIDb * (signed __int64)v5) >> 16);
    }
    v40 = v17;
    v28 = abs(v16);
    if ( abs(X_4) >= v28 )
    {
      LODWORD(v29) = 0;
      HIDWORD(v29) = SLOWORD(pOutdoorCamera->int_fov_rad);
      v30 = v29 / X_4;
      v6->field_58 = v30;
      v31 = v6->field_58;
      v6->uScreenSpaceX = pViewport->uScreenCenterX
                        - ((signed int)((unsigned __int64)(v30 * (signed __int64)v16) >> 16) >> 16);
      v32 = v6->flt_28;
      v33 = (signed int)((unsigned __int64)(v31 * (signed __int64)v40) >> 16) >> 16;
      v34 = pViewport->uScreenCenterY - v33;
      v6->uScreenSpaceY = pViewport->uScreenCenterY - v33;
      v35 = v32;
      v6->field_58 = (unsigned __int64)(_48B561_mess_with_scaling_along_z(/*v34, */v35) * (signed __int64)v6->field_58) >> 16;
      v6->field_50 = X_4;
      v36 = v6->uScreenSpaceX;
      if ( v36 >= (signed int)pViewport->uViewportX )
      {
        if ( v36 < (signed int)pViewport->uViewportZ )
        {
          v37 = v6->uScreenSpaceY;
          if ( v37 >= (signed int)pViewport->uViewportY )
          {
            if ( v37 < (signed int)pViewport->uViewportW )
              return 1;
          }
        }
      }
    }
  }
  return 0;
}

//----- (0048BBA6) --------------------------------------------------------
void ParticleEngine::DrawParticles_BLV()
{
  ParticleEngine *v1; // esi@1
  int v2; // eax@1
  unsigned __int8 v3; // zf@1
  char v4; // sf@1
  unsigned __int8 v5; // of@1
  Render *v6; // ebx@2
  char *v7; // edi@2
  signed int v8; // ecx@7
  int v9; // eax@10
  signed int v10; // eax@12
  int v11; // eax@18
  int v12; // ecx@20
  int v13; // edx@20
  Particle *v14; // eax@28
  RenderBillboardTransform_local0 v15; // [sp+Ch] [bp-58h]@1
  int v16; // [sp+5Ch] [bp-8h]@5
  int v17; // [sp+60h] [bp-4h]@1

  v15.uParentBillboardID = -1;
  v1 = this;
  v2 = this->uStartParticle;
  v5 = __OFSUB__(v2, this->uEndParticle);
  v3 = v2 == this->uEndParticle;
  v4 = v2 - this->uEndParticle < 0;
  v17 = this->uStartParticle;
  if ( (unsigned __int8)(v4 ^ v5) | v3 )
  {
    v6 = pRenderer;
    v7 = (char *)&this->pParticles[v2].field_54 + 2;
    do
    {
      if ( *(int *)(v7 - 86) )
      {
        if ( v1->ViewProject_TrueIfStillVisible(v2) )
        {
          v16 = *(int *)(v7 - 22);
          if ( v16 >= (signed int)pBLVRenderParams->uViewportX )
          {
            if ( v16 < (signed int)pBLVRenderParams->uViewportZ )
            {
              v8 = *(int *)(v7 - 18);
              if ( v8 >= (signed int)pBLVRenderParams->uViewportY )
              {
                if ( v8 < (signed int)pBLVRenderParams->uViewportW )
                {
                  if ( pRenderer->pRenderD3D )
                  {
                    v9 = *(int *)(v7 - 86);
                    if ( BYTE1(v9) & 1 )
                    {
                      v14 = &v1->pParticles[v17];
                      v15.field_10 = v14->field_58 >> 2;
                      v15.field_14 = v14->field_58 >> 2;
                      v15.field_8 = v14->uScreenSpaceX;
                      v15.field_C = v14->uScreenSpaceY;
                      v15.field_28 = v14->field_50;
                      pRenderer->MakeParticleBillboardAndPush_BLV(&v15, 0, v14->uLightColor, v14->_rotation);
                      return;
                    }
                    if ( BYTE1(v9) & 2 )
                    {
                      v10 = v1->pLines.uNumLines;
                      if ( v10 < 100 )
                      {
                        v1->pLines.pLineVertices[2 * v10].pos.x = (double)v16;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.y = (double)*(signed int *)(v7 - 18);
                        v16 = *((short *)v7 - 2);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.z = 1.0
                                                                                 - 1.0 / ((double)v16 * 0.061758894);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].rhw = 1.0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].diffuse = *(int *)(v7 + 14);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].specular = 0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].texcoord.x = 0.0;
                        *((float *)&v1->pParticles[0].bFree + 16 * (v1->pLines.uNumLines + 813)) = 0.0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.x = (double)*(signed int *)(v7 - 14);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.y = (double)*(signed int *)(v7 - 10);
                        v16 = *(short *)v7;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.z = 1.0
                                                                                     - 1.0 / ((double)v16 * 0.061758894);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].rhw = 1.0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].diffuse = *(int *)(v7 + 14);
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].specular = 0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].texcoord.x = 0.0;
                        v1->pLines.pLineVertices[2 * v1->pLines.uNumLines++ + 1].texcoord.y = 0.0;
                      }
                    }
                    if ( *(v7 - 85) & 4 )
                    {
                      v15.field_10 = *(int *)(v7 + 2);
                      v15.field_14 = *(int *)(v7 + 2);
                      v15.field_8 = *(int *)(v7 - 22);
                      v15.field_C = *(int *)(v7 - 18);
                      v15.field_28 = *(int *)(v7 - 6);
                      pRenderer->MakeParticleBillboardAndPush_BLV(
                        &v15,
                        pBitmaps_LOD->pHardwareTextures[*(int *)(v7 - 50)],
                        *(int *)(v7 + 14),
                        *(int *)(v7 - 26));
                    }
                    if ( *(v7 - 85) & 8 )
                    {
                      v15.field_10 = *(int *)(v7 + 2);
                      v15.field_14 = *(int *)(v7 + 2);
                      v15.field_8 = *(int *)(v7 - 22);
                      v15.field_C = *(int *)(v7 - 18);
                      v15.field_28 = *(int *)(v7 - 6);
                      pRenderer->MakeParticleBillboardAndPush_BLV(
                        &v15,
                        pSprites_LOD->pHardwareSprites[*(int *)(v7 - 50)].pTexture,
                        *(int *)(v7 + 14),
                        *(int *)(v7 - 26));
                    }
                  }
                  else
                  {
                    v11 = 13 * *(int *)(v7 + 2) >> 16;
                    if ( v11 > 30 )
                      v11 = 30;
                    v12 = v8 - v11;
                    v13 = v16 - (v11 >> 1);
                    if ( v13 + v11 < (signed int)pViewport->uViewportX
                      || v13 >= (signed int)pViewport->uViewportZ
                      || v12 + v11 < (signed int)pViewport->uViewportY
                      || v12 >= (signed int)pViewport->uViewportW )
                    {
                      v6 = pRenderer;
                    }
                    else
                    {
                      v6 = pRenderer;
                      pRenderer->_4A48E4(v13, v12, *(int *)(v7 - 6), *(int *)(v7 + 14), v11);
                    }
                  }
                }
              }
            }
          }
        }
      }
      v7 += 104;
      v2 = v17 + 1;
      v5 = __OFSUB__(v17 + 1, v1->uEndParticle);
      v3 = v17 + 1 == v1->uEndParticle;
      v4 = v17++ + 1 - v1->uEndParticle < 0;
    }
    while ( (unsigned __int8)(v4 ^ v5) | v3 );
  }
}

//----- (0048BEEF) --------------------------------------------------------
void ParticleEngine::DrawParticles_ODM()
{
  ParticleEngine *v1; // esi@1
  int v2; // eax@1
  unsigned __int8 v3; // zf@1
  char v4; // sf@1
  unsigned __int8 v5; // of@1
  Render *pRender; // ebx@2
  char *v7; // edi@2
  int v8; // eax@6
  signed int v9; // eax@8
  int v10; // eax@14
  int v11; // ecx@16
  int v12; // edx@16
  Particle *v13; // eax@24
  stru346 v14; // [sp+Ch] [bp-58h]@1
  int v15; // [sp+5Ch] [bp-8h]@9
  int v16; // [sp+60h] [bp-4h]@1

  v14.uParentBillboardID = -1;
  v1 = this;
  v2 = this->uStartParticle;
  v5 = __OFSUB__(v2, this->uEndParticle);
  v3 = v2 == this->uEndParticle;
  v4 = v2 - this->uEndParticle < 0;
  v16 = this->uStartParticle;
  if ( (unsigned __int8)(v4 ^ v5) | v3 )
  {
    pRender = pRenderer;
    v7 = (char *)&this->pParticles[v2].field_50 + 2;
    do
    {
      if ( *(int *)(v7 - 82) && v1->_48B5B3(v2) )
      {
        if ( pRenderer->pRenderD3D )
        {
          v8 = *(int *)(v7 - 82);
          if ( BYTE1(v8) & 1 )
          {
            v13 = &v1->pParticles[v16];
            v14.field_10 = v13->field_58 >> 2;
            v14.field_14 = v13->field_58 >> 2;
            v14.field_8 = v13->uScreenSpaceX;
            v14.field_C = v13->uScreenSpaceY;
            v14.field_28 = v13->field_50;
            pRenderer->MakeParticleBillboardAndPush_ODM(
              (RenderBillboardTransform_local0 *)&v14,
              0,
              v13->uLightColor,
              v13->_rotation);
            return;
          }
          if ( BYTE1(v8) & 2 )
          {
            v9 = v1->pLines.uNumLines;
            if ( v9 < 100 )
            {
              v1->pLines.pLineVertices[2 * v9].pos.x = (double)*(signed int *)(v7 - 18);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.y = (double)*(signed int *)(v7 - 14);
              v15 = *(short *)v7;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].pos.z = 1.0
                                                                       - 1.0
                                                                       / ((double)v15
                                                                        * 1000.0
                                                                        / (double)pOutdoorCamera->shading_dist_mist);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].rhw = 1.0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].diffuse = *(int *)(v7 + 18);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].specular = 0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines].texcoord.x = 0.0;
              *((float *)&v1->pParticles[0].bFree + 16 * (v1->pLines.uNumLines + 813)) = 0.0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.x = (double)*(signed int *)(v7 - 10);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.y = (double)*(signed int *)(v7 - 6);
              v15 = *(short *)v7;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].pos.z = 1.0
                                                                           - 1.0
                                                                           / ((double)v15
                                                                            * 1000.0
                                                                            / (double)pOutdoorCamera->shading_dist_mist);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].rhw = 1.0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].diffuse = *(int *)(v7 + 18);
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].specular = 0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines + 1].texcoord.x = 0.0;
              v1->pLines.pLineVertices[2 * v1->pLines.uNumLines++ + 1].texcoord.y = 0.0;
            }
          }
          if ( *(v7 - 81) & 4 )
          {
            v14.field_10 = *(int *)(v7 + 6);
            v14.field_14 = *(int *)(v7 + 6);
            v14.field_8 = *(int *)(v7 - 18);
            v14.field_C = *(int *)(v7 - 14);
            v14.field_28 = *(int *)(v7 - 2);
            pRenderer->MakeParticleBillboardAndPush_ODM(
              (RenderBillboardTransform_local0 *)&v14,
              pBitmaps_LOD->pHardwareTextures[*(int *)(v7 - 46)],
              *(int *)(v7 + 18),
              *(int *)(v7 - 22));
          }
          if ( *(v7 - 81) & 8 )
          {
            v14.field_10 = *(int *)(v7 + 6);
            v14.field_14 = *(int *)(v7 + 6);
            v14.field_8 = *(int *)(v7 - 18);
            v14.field_C = *(int *)(v7 - 14);
            v14.field_28 = *(int *)(v7 - 2);
            pRenderer->MakeParticleBillboardAndPush_ODM(
              (RenderBillboardTransform_local0 *)&v14,
              pSprites_LOD->pHardwareSprites[*(int *)(v7 - 46)].pTexture,
              *(int *)(v7 + 18),
              *(int *)(v7 - 22));
          }
        }
        else
        {
          v10 = 13 * *(int *)(v7 + 6) >> 16;
          if ( v10 > 30 )
            v10 = 30;
          v11 = *(int *)(v7 - 18) - (v10 >> 1);
          v12 = *(int *)(v7 - 14) - v10;
          if ( v11 + v10 < (signed int)pViewport->uViewportX
            || v11 >= (signed int)pViewport->uViewportZ
            || *(int *)(v7 - 14) < (signed int)pViewport->uViewportY
            || v12 >= (signed int)pViewport->uViewportW )
          {
            pRender = pRenderer;
          }
          else
          {
            pRender = pRenderer;
            pRenderer->_4A48E4(v11, v12, *(int *)(v7 - 2), *(int *)(v7 + 18), v10);
          }
        }
      }
      v7 += 104;
      v2 = v16 + 1;
      v5 = __OFSUB__(v16 + 1, v1->uEndParticle);
      v3 = v16 + 1 == v1->uEndParticle;
      v4 = v16++ + 1 - v1->uEndParticle < 0;
    }
    while ( (unsigned __int8)(v4 ^ v5) | v3 );
  }
}