/////////////////////////////////////////////////////////////////////////////// // 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