xbox-kernel/private/ntos/ani2/VBlob.h
2020-09-30 17:17:25 +02:00

250 lines
5.6 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// File: VBlob.h
//
// Copyright 2001 Pipeworks Software
///////////////////////////////////////////////////////////////////////////////
#ifndef VBLOB_H
#define VBLOB_H
#include "qrand.h"
// The vertex list holding the unit sphere coordinates remain on the card.
// Each frame another list is streamed.
struct VBlobConstantVertex
{
D3DVECTOR unit_sphere_normal;
};
struct VBlobChangingVertex
{
D3DVECTOR4 normal; // not normalized (do it in the GPU); w is the displacement due to bumps
};
// Bloblets need to be able to be copied.
class VBloblet
{
public:
void Init() { fWobble = 1.0f; fWobbleDirection = 0.0f; }
void UnInit() {}
void set(float rad, float x, float y, float z)
{
fRadius = rad;
Set(&vPosition, x, y, z);
}
// Perturbation is normal * fMagnitude * f( (r*r)/(fRadius*fRadius) ).
// f(r/R) will start at a peak of 1 (at r=0) and fall to 0 as r goes to R. The
// slope at 0 and 1 will be 0.
// The perturbation needs to be applied in code so the normals can be accumulated.
float fRadius;
D3DVECTOR vPosition;
bool bFarSide;
D3DVECTOR vDirection;
float fStartTime;
float fTimeMultiple;
float fMaxDist; // in world units
float fCurDist; // fMaxDist * sin(...)
float fWobble;
float fWobbleDirection;
bool update(float elapsed_time, float dt); // returns false if it consents to be deleted
};
class VBlobBump
{
public:
void Init();
void UnInit();
void set(float rad, float mag, float x, float y, float z)
{
fRadius = rad;
fRadius2 = fRadius*fRadius;
fOORadius2 = 1.0f / fRadius2;
fMagnitude = mag;
Set(&vPosition, x, y, z);
}
// Perturbation is normal * fMagnitude * f( (r*r)/(fRadius*fRadius) ).
// f(r/R) will start at a peak of 1 (at r=0) and fall to 0 as r goes to R. The
// slope at 0 and 1 will be 0.
// The perturbation needs to be applied in code so the normals can be accumulated.
float fRadius, fRadius2, fOORadius2;
float fMagnitude; // wrt unit sphere
D3DVECTOR vPosition;
int facesOfInterest; // bitfield indicating the three faces (0,1,2,4,5) <-> (-x,-y,-z,+x,+y,+z) the blob points most toward
// returns true if it initialized a new Bloblet
bool create(float cur_time, VBloblet* p_bloblet); // randomly creates a blob bump
bool update(float elapsed_time, float dt, VBloblet* p_bloblet);
protected:
// Positioning data.
D3DVECTOR vDirection; // normalized
float fStartTime;
float fTimeMul;
float fMaxMagnitude;
VBloblet* pMyBloblet;
bool bStillAttachedToBloblet;
void recalculateFacesOfInterest();
};
class VBlob
{
protected:
LPDIRECT3DVERTEXBUFFER8 m_pBlobletVB; // VBlobConstantVertex, for the emerging blobs, lower tesselation
LPDIRECT3DINDEXBUFFER8 m_pBlobletIB;
LPDIRECT3DVERTEXBUFFER8 pHaloQuadVB;
LPDIRECT3DVERTEXBUFFER8 m_pBlobVBConst; // VBlobConstantVertex
LPDIRECT3DVERTEXBUFFER8 m_pBlobVBChangingR; // VBlobChangingVertex (rendering version) (swapped in render)
LPDIRECT3DVERTEXBUFFER8 m_pBlobVBChangingU; // VBlobChangingVertex (updating version)
LPDIRECT3DINDEXBUFFER8 m_pBlobIB;
D3DVECTOR* m_pUnitSphereNormals;
DWORD m_dwNumVertices, m_dwNumBlobletVertices;
DWORD m_dwNumIndices, m_dwNumBlobletIndices;
int m_NumVertsPerFace;
DWORD m_dwVShaderBlob, m_dwVShaderBloblet;
DWORD m_dwPShaderBlob, m_dwPShaderBloblet;
D3DVECTOR4 m_BlobColor;
D3DVECTOR m_Pos; // position of center
D3DVECTOR m_Scale;
FLOAT m_fRadius;
// BlobBumps work in unit-sphere space.
enum { MAX_BLOBBUMPS = 32 };
VBlobBump m_BlobBumps[MAX_BLOBBUMPS];
int m_NumBlobBumps;
enum { MAX_BLOBLETS = 8 };
VBloblet m_Bloblets[MAX_BLOBLETS];
int m_NumBloblets;
static QRand m_QRand;
// Creates a VBlobConstantVertex vertex buffer. Creates WORD index buffer.
static bool generateUnitSphere(
int resolution,
LPDIRECT3DVERTEXBUFFER8* pp_vb,
LPDIRECT3DINDEXBUFFER8* pp_ib,
D3DVECTOR** pp_us,
DWORD* num_verts, DWORD* num_indices);
void prepareChangingVertices();
void zeroChangingVertices(); // zeros bumps in m_pBlobVBChangingU
inline void swapChangingVertices()
{
LPDIRECT3DVERTEXBUFFER8 temp = m_pBlobVBChangingR;
m_pBlobVBChangingR = m_pBlobVBChangingU;
m_pBlobVBChangingU = temp;
}
public:
void Init();
void UnInit()
{
int i;
for (i = 0; i < MAX_BLOBBUMPS; i++)
{
m_BlobBumps[i].UnInit();
}
for (i = 0; i < MAX_BLOBLETS; i++)
{
m_Bloblets[i].UnInit();
}
destroy();
}
void create();
void destroy();
void render();
void advanceTime(float fElapsedTime, float fDt);
void restart();
float getRadius() const { return m_fRadius; }
const D3DVECTOR& getCenter() const { return m_Pos; }
void getLightForPosition(D3DVECTOR* p_light_pos, float* p_intensity, D3DVECTOR position);
static inline float fRand01();
static inline float fRand11();
};
extern VBlob* gpVBlob;
#define LLI_RAND_MAX 0x00010000
#define LLI_RAND_MASK 0x0000FFFF
float VBlob::fRand01()
{
static float mul = 1.0f / ((float)LLI_RAND_MAX);
return ((float)(m_QRand.Rand()&LLI_RAND_MASK)) * mul;
}
float VBlob::fRand11()
{
static float mul = 2.0f / ((float)LLI_RAND_MAX);
return (((float)(m_QRand.Rand()&LLI_RAND_MASK)) * mul) - 1.0f;
}
#endif // VBLOB_H