729 lines
20 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
///////////////////////////////////////////////////////////////////////////////
// File: Blobs.cpp
//
// Copyright 2001 Pipeworks Software
///////////////////////////////////////////////////////////////////////////////
#include <xtl.h>
#include "xbs_math.h"
#include "xbs_app.h"
#include "qrand.h"
#include "Blobs.h"
const LavaLampInterior* LLBlob::spLL = NULL;
QRand LavaLampInterior::m_QRand;
void LavaLampInterior::destroy()
{
//MTS m_BlobRenderer.destroy();
for (int i=0; i<NUM_LLBLOBS; i++)
{
m_Blobs[i].destroy();
}
if( m_dwPixelShader )
{
gpd3dDev->DeletePixelShader( m_dwPixelShader );
m_dwPixelShader = 0;
}
if ( m_dwVertexShader )
{
gpd3dDev->DeleteVertexShader( m_dwVertexShader );
m_dwVertexShader = 0;
}
}
LLBlob::LLBlob()
{
m_pBlobVB = NULL;
m_pBlobIB = NULL;
m_Temperature = 0.5f;
Set(&m_Accel, 0.0f, 0.0f, 0.0f);
Set(&m_Velocity, 0.0f, 0.0f, 0.0f);
m_DeformationInertia = 0.3f;
}
void LLBlob::destroy()
{
if (m_pBlobVB)
{
m_pBlobVB->Release();
m_pBlobVB = NULL;
}
if (m_pBlobIB)
{
m_pBlobIB->Release();
m_pBlobIB = NULL;
}
}
void LavaLampInterior::InitPixelShader()
{
if( m_dwPixelShader )
{
gpd3dDev->DeletePixelShader( m_dwPixelShader );
m_dwPixelShader = 0;
}
m_dwPixelShader = gApp.loadPixelShader("D:\\Shaders\\blob.xpu");
}
void LavaLampInterior::create()
{
LLBlob::spLL = this;
m_ConicSectionCenterX = +0.04f;
m_ConicSectionCenterY = -0.082f;
m_NumConicSections = 2;
m_ConicSectionBotZ[0] = -0.47f;
m_ConicSectionBotZ[1] = -0.25f;
m_ConicSectionBotZ[2] = +0.35f;
m_ConicSectionRadius[0] = 0.11f;
m_ConicSectionRadius[1] = 0.25f;
m_ConicSectionRadius[2] = 0.12f;
int i;
for (i=0; i<m_NumConicSections; i++)
{
m_ConicSectionSlope[i] = (m_ConicSectionRadius[i+1] - m_ConicSectionRadius[i+0]) /
(m_ConicSectionBotZ[i+1] - m_ConicSectionBotZ[i+0]);
float norm = 1.0f / sqrtf(1 + m_ConicSectionSlope[i]*m_ConicSectionSlope[i]);
m_ConicSectionNormalR[i] = norm * -1.0f;
m_ConicSectionNormalZ[i] = norm * m_ConicSectionSlope[i];
}
// Initialize pixel shader
InitPixelShader();
DWORD dwShaderVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position
D3DVSD_END()
};
m_dwVertexShader = gApp.loadVertexShader("D:\\Shaders\\blob.xvu", dwShaderVertexDecl);
float bot = m_ConicSectionBotZ[0];
float sx = m_ConicSectionCenterX - 0.1f;
float sy = m_ConicSectionCenterY - 0.1f;
for (i=0; i<NUM_LLBLOBS; i++)
{
D3DVECTOR pos;
D3DVECTOR4 color, base_color;
Set(&pos, m_ConicSectionCenterX, m_ConicSectionCenterY, m_ConicSectionBotZ[m_NumConicSections>>1] );
Set(&color, (i&0x04) ? 0.0f : 1.0f, (i&0x02) ? 0.0f : 1.0f, (i&0x01) ? 0.0f : 1.0f, 1.0f);
Set(&base_color, 0.724f, 0.732f, 0.556f, 1.0f);
//MTS m_Blobs[i].create(pos, color*0.1f + base_color*0.9f);
m_Blobs[i].create(pos, base_color);
m_Blobs[i].setSpecies(i);
}
//MTS m_BlobRenderer.create();
//MTS m_BlobRenderer.init(this, &m_Blobs[0], NUM_LLBLOBS, 0.01f, 0.01f, m_ConicSectionCenterX, m_ConicSectionCenterY);
return;
};
void LLBlob::calcFacePoint(D3DVECTOR* ppos, int face, int u, int v)
{
float fu = (u==m_Subdivisions) ? +1.0f : -1.0f + m_fDivisionStep * ((float)u);
float fv = (v==m_Subdivisions) ? +1.0f : -1.0f + m_fDivisionStep * ((float)v);
switch(face)
{
case 0: Set(ppos, -1.0f, -fu, +fv); break;
case 1: Set(ppos, +fv, -1.0f, -fu); break;
case 2: Set(ppos, -fu, +fv, -1.0f); break;
case 3: Set(ppos, +1.0f, +fu, +fv); break;
case 4: Set(ppos, +fv, +1.0f, +fu); break;
case 5: Set(ppos, +fu, +fv, +1.0f); break;
}
}
void LLBlob::create(D3DVECTOR pos, D3DVECTOR4 color)
{
// A blob is modeled as a subdivided cube.
m_BlobColor = color;
m_Pos = pos;
Set(&m_Scale, 0.9f, 0.9f, 0.9f);
m_DeformationInertia = spLL->fRand11() * 0.1f;
m_fRadius = LavaLampInterior::fRand01();
m_fRadius = 0.5f * (m_fRadius*m_fRadius + LavaLampInterior::fRand01());
m_fRadius = 0.03f + 0.05f * m_fRadius;
m_TemperatureAbsorbance = 0.05f / m_fRadius; // is just representational
m_Temperature = 0.5f + 0.2f * LavaLampInterior::fRand11();
m_Subdivisions = 4; // face is a grid of sd+1 quads square
m_fDivisionStep = 2.0f / m_Subdivisions;
//MTS m_dwNumVertices = 2*(subdivisions+2)*(subdivisions+2) + 4*subdivisions*(subdivisions+1); // number of unique vertices
m_dwNumVertices = 6*(m_Subdivisions+1)*(m_Subdivisions+1);
m_dwNumIndices = 6*(m_Subdivisions)*(m_Subdivisions)*2*3;
gpd3dDev->CreateVertexBuffer( m_dwNumVertices * sizeof(BlobVertex), 0, 0, 0, &m_pBlobVB);
gpd3dDev->CreateIndexBuffer( m_dwNumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pBlobIB);
BlobVertex* p_verts;
WORD* p_indices;
m_pBlobVB->Lock(0, 0, (BYTE**)&p_verts, 0);
m_pBlobIB->Lock(0, 0, (BYTE**)&p_indices, 0);
// Create vertices.
BlobVertex* p_vert = &p_verts[0];
for (int k=0; k<6; k++)
{
for (int j=0; j<=m_Subdivisions; j++)
{
for (int i=0; i<=m_Subdivisions; i++)
{
calcFacePoint(&p_vert->pos, k, i, j);
float oo_dist = 1.0f / sqrtf(p_vert->pos.x*p_vert->pos.x + p_vert->pos.y*p_vert->pos.y + p_vert->pos.z*p_vert->pos.z);
p_vert->pos.x *= oo_dist;
p_vert->pos.y *= oo_dist;
p_vert->pos.z *= oo_dist;
p_vert++;
}
}
}
// Create indices.
WORD* p_index = &p_indices[0];
for (int k=0; k<6; k++)
{
int face_start = k*(m_Subdivisions+1)*(m_Subdivisions+1);
for (int j=0; j<m_Subdivisions; j++)
{
for (int i=0; i<m_Subdivisions; i++)
{
*(p_index++) = face_start + (j+0)*(m_Subdivisions+1) + (i+0);
*(p_index++) = face_start + (j+0)*(m_Subdivisions+1) + (i+1);
*(p_index++) = face_start + (j+1)*(m_Subdivisions+1) + (i+0);
*(p_index++) = face_start + (j+1)*(m_Subdivisions+1) + (i+1);
*(p_index++) = face_start + (j+1)*(m_Subdivisions+1) + (i+0);
*(p_index++) = face_start + (j+0)*(m_Subdivisions+1) + (i+1);
}
}
}
m_pBlobVB->Unlock();
m_pBlobIB->Unlock();
}
void LavaLampInterior::advanceTime(float fElapsedTime, float fDt)
{
if (fDt < 0.0f) fDt = 0.0f;
if (fDt > 0.1f) fDt = 0.1f;
//MTS m_BlobRenderer.advanceTime(fElapsedTime, fDt);
for (int i=0; i<NUM_LLBLOBS; i++)
{
m_Blobs[i].advanceTime(fElapsedTime, fDt);
}
recomputeSpecie();
}
void LLBlob::advanceTime(float fElapsedTime, float fDt)
{
float ambient_temp = spLL->getTemperature(m_Pos.z);
float scale = 0.002f * m_TemperatureAbsorbance*m_TemperatureAbsorbance * fDt;
m_Temperature += scale * (ambient_temp - m_Temperature);
// For purposes of the simulation, water stays at a constant density.
// A blob's density is equal to water at temperature 0.5f. For each unit
// of temperature difference, an acceleration of 1.0 m/s/s is applied.
m_Velocity.z += fDt * 1.0f * (m_Temperature-0.5f);
m_Accel.x += LavaLampInterior::fRand11() * fDt;
m_Accel.y += LavaLampInterior::fRand11() * fDt;
m_Accel.z += LavaLampInterior::fRand11() * fDt;
//MTS m_Velocity.x += LavaLampInterior::fRand11() * fDt * fDt;
//MTS m_Velocity.y += LavaLampInterior::fRand11() * fDt * fDt;
//MTS m_Velocity.z += LavaLampInterior::fRand11() * fDt * fDt;
m_Accel.x = min(+0.05f, max(-0.05f, m_Accel.x));
m_Accel.y = min(+0.05f, max(-0.05f, m_Accel.y));
m_Accel.z = min(+0.05f, max(-0.05f, m_Accel.z));
if (Length2(m_Accel) > 1.0f) Scale(&m_Accel, 0.96f);
// Friction moving through water.
AddScaled(&m_Velocity, m_Accel, fDt);
float vel2 = Length2(m_Velocity);
Scale(&m_Velocity, 1.0f - fDt * 120.0f * vel2);
AddScaled(&m_Pos, m_Velocity, fDt);
// Do collisions.
spLL->collide(this, m_Pos.x, m_Pos.y, m_Pos.z, m_fRadius, fDt);
// Adjust render wobble.
m_Scale.x += m_DeformationInertia * fDt * m_TemperatureAbsorbance;
m_Scale.y += m_DeformationInertia * fDt * m_TemperatureAbsorbance;
m_Scale.z = 0.9f - (m_Scale.x - 0.9f) * (0.9f+0.9f)*0.9f / (0.9f*0.9f);
float accel;
if (m_DeformationInertia > 0.0f)
{
accel = 0.91f - m_Scale.x;
}
else
{
accel = 0.89f - m_Scale.x;
}
m_DeformationInertia += 20.0f * accel * fDt;
m_DeformationInertia = max(-0.3f, min(+0.3f, m_DeformationInertia));
}
float LavaLampInterior::getTemperature(float z) const
{
float dz = -0.5f + (z - m_ConicSectionBotZ[0]) / (m_ConicSectionBotZ[m_NumConicSections] - m_ConicSectionBotZ[0]);
dz *= 2.6f;
dz *= dz*dz;
return max(0.0f, min(1.0f, 0.5f - dz));
}
bool LavaLampInterior::collideWithCaps(LLBlob* pllb, float x, float y, float z, float radius) const
{
if (z - radius < m_ConicSectionBotZ[0])
{
D3DVECTOR pos, norm;
Set(&pos, x, y, m_ConicSectionBotZ[0] + radius + 0.001f);
Set(&norm, 0.0f, 0.0f, +1.0f);
pllb->collided(pos, norm);
return true;
}
if (z + radius > m_ConicSectionBotZ[m_NumConicSections])
{
D3DVECTOR pos, norm;
Set(&pos, x, y, m_ConicSectionBotZ[m_NumConicSections] - radius - 0.001f);
Set(&norm, 0.0f, 0.0f, -1.0f);
pllb->collided(pos, norm);
return true;
}
return false;
}
void LavaLampInterior::collide(LLBlob* pllb, float x, float y, float z, float radius, float dt) const
{
// Bounce off the caps.
if (collideWithCaps(pllb, x, y, z, radius))
{
z = pllb->getPos().z;
}
x -= m_ConicSectionCenterX;
y -= m_ConicSectionCenterY;
float r = sqrtf( x*x + y*y );
// Check the conic sections. Check the surfaces first, the corners will be checked afterwards.
int i;
bool b_hit_wall = false;
for (i=0; i<m_NumConicSections; i++)
{
if (m_ConicSectionBotZ[i+1] < z - radius) continue;
if (m_ConicSectionBotZ[i+0] > z + radius) break;
// Sphere overlaps the section at least somewhat. Find the nearest
// point on the cone surface and see if that is within the range.
float dz = z - m_ConicSectionBotZ[i];
float dr = r - m_ConicSectionRadius[i];
float overlap = radius - (dr*m_ConicSectionNormalR[i] + dz*m_ConicSectionNormalZ[i]);
if (overlap < 0.0f) continue;
// Calculate distance along surface to the nearest point of collision.
float s = dr*m_ConicSectionNormalZ[i] - dz*m_ConicSectionNormalR[i];
if (s<0.0f) continue;
float height = m_ConicSectionBotZ[i+1]-m_ConicSectionBotZ[i];
if (s*s > height*height * (1.0f + m_ConicSectionSlope[i]*m_ConicSectionSlope[i])) continue;
// Collision.
float nz = m_ConicSectionNormalZ[i];
float oo_r = 1.0f / max(0.001f, r);
float nx = x * oo_r * m_ConicSectionNormalR[i];
float ny = y * oo_r * m_ConicSectionNormalR[i];
D3DVECTOR pos, norm;
x += nx*overlap;
y += ny*overlap;
z += nz*overlap;
r = sqrtf( x*x + y*y ); // recompute radius
Set(&pos, m_ConicSectionCenterX + x, m_ConicSectionCenterY + y, z);
Set(&norm, nx, ny, nz);
pllb->collided(pos, norm);
b_hit_wall = true;
}
// Check the corners.
if (!b_hit_wall) for (i=0; i<m_NumConicSections; i++)
{
if (m_ConicSectionBotZ[i+1] < z - radius) continue;
if (m_ConicSectionBotZ[i+0] > z + radius) break;
float dz = z - m_ConicSectionBotZ[i];
float dr = r - m_ConicSectionRadius[i];
if (dz*dz + dr*dr > radius*radius) continue;
float dist = sqrtf(dz*dz + dr*dr);
float overlap = radius - dist;
float f_norm = 1.0f / max(0.001f, dist);
float nz = -dz * f_norm;
float nr = -dr * f_norm;
float oo_r = 1.0f / max(0.001f, r);
float nx = x * oo_r * nr;
float ny = y * oo_r * nr;
D3DVECTOR pos, norm;
x += nx*overlap;
y += ny*overlap;
z += nz*overlap;
r = sqrtf( x*x + y*y ); // recompute radius
Set(&pos, m_ConicSectionCenterX + x, m_ConicSectionCenterY + y, z);
Set(&norm, nx, ny, nz);
pllb->collided(pos, norm);
b_hit_wall = true;
}
// Check other blobs.
for (i=0; i<NUM_LLBLOBS; i++)
{
if (&m_Blobs[i] == pllb) continue;
D3DVECTOR delta;
Sub(m_Blobs[i].getPos(), pllb->getPos(), &delta);
float rad = (m_Blobs[i].getRadius() + pllb->getRadius());
if (Length2(delta) > rad*rad) continue;
pllb->interactWithBlob(&m_Blobs[i], dt);
}
if (collideWithCaps(pllb, x + m_ConicSectionCenterX, y + m_ConicSectionCenterY, z, radius))
{
// Should never happen with convex hull.
z = pllb->getPos().z;
}
}
void LLBlob::collided(D3DVECTOR pos, D3DVECTOR normal)
{
D3DVECTOR diff;
Sub(pos, m_Pos, &diff);
if (Length2(diff) > 0.5f * m_fRadius * m_fRadius)
{
int a = 0;
}
float dot;
dot = Dot(normal, m_Accel);
if (dot<0.0f) AddScaled(&m_Accel, normal, -dot);
dot = Dot(normal, m_Velocity);
if (dot<0.0f) AddScaled(&m_Velocity, normal, -dot);
m_Pos = pos;
}
void LLBlob::interactWithBlob(const LLBlob* pllb, float dt)
{
// Attract at range, repel when close.
float mass_b = pllb->m_fRadius;
mass_b *= mass_b*mass_b;
D3DVECTOR delta;
Sub(pllb->getPos(), getPos(), &delta);
float dist2 = Length2(delta);
if (dist2 < 0.000001f) return;
D3DVECTOR delta_v;
Sub(pllb->m_Velocity, m_Velocity, &delta_v);
float f_part_mag = Dot(delta_v, delta);
if (getSpecies() == pllb->getSpecies())
{
// Same species.
float extreme_rad = (m_fRadius + pllb->m_fRadius);
float attract = mass_b * dt * 10000.0f * ((f_part_mag > 0.0f) ? 1.0f : 0.5f);
AddScaled(&m_Velocity, delta, attract);
//MTS float attract = ((1.0f / dist2) - (1.0f / (extreme_rad*extreme_rad))) * mass_b * dt * 5.0f;
//MTS AddScaled(&m_Accel, delta, attract);
// Should try adding to the velocity directly...
extreme_rad *= 0.6f;
float extreme_rad2 = extreme_rad*extreme_rad;
float repel = ((1.0f / min(extreme_rad2*0.04f, dist2)) - (1.0f / extreme_rad2)) * mass_b * dt * 5.0f;
repel *= ((f_part_mag > 0.0f) ? 0.3f : 1.0f);
if (repel > 0.0f) AddScaled(&m_Velocity, delta, -repel);
//MTS float repel = ((1.0f / min(extreme_rad2*0.04f, dist2)) - (1.0f / extreme_rad2)) * mass_b * dt * 500.0f;
//MTS if (repel > 0.0f) AddScaled(&m_Accel, delta, -repel);
}
else
{
// Different specie.
float extreme_rad2 = (m_fRadius + pllb->m_fRadius);
extreme_rad2 *= extreme_rad2;
float repel = ((1.0f / min(extreme_rad2*0.04f, dist2)) - (1.0f / extreme_rad2)) * mass_b * dt * 1.0f;
repel *= ((f_part_mag > 0.0f) ? 0.3f : 1.0f);
AddScaled(&m_Velocity, delta, -repel);
//MTS float repel = ((1.0f / min(extreme_rad2*0.04f, dist2)) - (1.0f / extreme_rad2)) * mass_b * dt * 50.0f;
//MTS AddScaled(&m_Accel, delta, -repel);
}
}
void LavaLampInterior::recomputeSpecie()
{
int prev_species[NUM_LLBLOBS];
int i;
for (i=0; i<NUM_LLBLOBS; i++)
{
prev_species[i] = m_Blobs[i].getSpecies();
m_Blobs[i].setSpecies(i);
}
for (i=0; i<NUM_LLBLOBS-1; i++)
{
for (int j=i+1; j<NUM_LLBLOBS; j++)
{
D3DVECTOR diff;
Sub(m_Blobs[i].getPos(), m_Blobs[j].getPos(), &diff);
float dist2 = Length2(diff);
if (prev_species[i] == prev_species[j])
{
// Were connected.
float radii2 = m_Blobs[i].getRadius() + m_Blobs[j].getRadius();
radii2 *= radii2;
if (dist2 < 0.9f*0.9f * radii2)
{
// Are still touching. Maintain the same specie.
m_Blobs[j].setSpecies( m_Blobs[i].getSpecies() );
}
}
else
{
// Were not connected.
float check_rad = max(m_Blobs[i].getRadius(), m_Blobs[j].getRadius());
check_rad += 0.7f * min(m_Blobs[i].getRadius(), m_Blobs[j].getRadius());
if (dist2 < check_rad*check_rad)
{
// Connect them only if they are in the top or bottom.
bool b_close_to_end = false;
float z = m_Blobs[i].getPos().z;
float r = m_Blobs[i].getRadius();
b_close_to_end = b_close_to_end || (z - m_ConicSectionBotZ[0] < 1.5f * r);
b_close_to_end = b_close_to_end || (m_ConicSectionBotZ[m_NumConicSections] - z < 1.5f * r);
z = m_Blobs[j].getPos().z;
r = m_Blobs[j].getRadius();
b_close_to_end = b_close_to_end || (z - m_ConicSectionBotZ[0] < 1.5f * r);
b_close_to_end = b_close_to_end || (m_ConicSectionBotZ[m_NumConicSections] - z < 1.5f * r);
if (b_close_to_end)
{
m_Blobs[j].setSpecies( m_Blobs[i].getSpecies() );
}
}
}
}
}
for (i=0; i<NUM_LLBLOBS; i++)
{
m_Blobs[i].setSpecies( m_Blobs[m_Blobs[i].getSpecies()].getSpecies() );
}
// For debug purposes, color code the blobs based on specie.
for (i=0; i<NUM_LLBLOBS; i++)
{
D3DVECTOR4 color, base_color;
int s = m_Blobs[i].getSpecies();
Set(&color, (s&0x04) ? 0.0f : 1.0f, (s&0x02) ? 0.0f : 1.0f, (s&0x01) ? 0.0f : 1.0f, 1.0f);
Set(&base_color, 0.724f, 0.732f, 0.556f, 1.0f);
color.x = color.x*0.05f + base_color.x*0.95f;
color.y = color.y*0.05f + base_color.y*0.95f;
color.z = color.z*0.05f + base_color.z*0.95f;
color.w = color.w*0.05f + base_color.w*0.95f;
//MTS m_Blobs[i].setColor(color);
}
}
void LavaLampInterior::render()
{
// Set default states
gpd3dDev->SetRenderState( D3DRS_LIGHTING, FALSE );
gpd3dDev->SetRenderState( D3DRS_ZENABLE, TRUE );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
gpd3dDev->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
gpd3dDev->SetRenderState( D3DRS_ALPHAREF, 0x00000001 );
gpd3dDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
//MTS gpd3dDev->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
gpd3dDev->SetTexture( 0, gApp.pNormalCubeMap );
gpd3dDev->SetVertexShader( m_dwVertexShader );
gpd3dDev->SetPixelShader( m_dwPixelShader );
// Note: when passing matrices to a vertex shader, we transpose them, since
// matrix multiplies are done with dot product operations on the matrix rows.
D3DMATRIX matFinal,matTmp;
MulMats(gApp.theCamera.matWTC,gApp.theCamera.matProj,&matTmp);
SetTranspose(matTmp,&matFinal);
gpd3dDev->SetVertexShaderConstant(4,(CONST void *)&matFinal,4);
//; Expected vertex shaders constants
//; c0-c3 = Transpose of world matrix
//; c4-c7 = Transpose of view*projection matrix
//; c8 = some constants, x=0, y=1, z=2, w=0.5
D3DVECTOR4 val;
// Constants
Set(&val, 0.0f, 1.0f, 2.0f, 0.5f);
gpd3dDev->SetVertexShaderConstant( 8, &val, 1 );
//MTS m_BlobRenderer.render();
for (int i=0; i<NUM_LLBLOBS; i++)
{
m_Blobs[i].render();
}
// Restore the state
gpd3dDev->SetPixelShader( NULL );
gpd3dDev->SetVertexShader( NULL );
gpd3dDev->SetTexture(0, NULL);
}
void LLBlob::render()
{
// Make the object to World transform. Transpose it.
D3DMATRIX matT, mat;
SetIdentity( &mat );
mat.m[0][0] = m_Scale.x * m_fRadius;
mat.m[1][1] = m_Scale.y * m_fRadius;
mat.m[2][2] = m_Scale.z * m_fRadius;
mat.m[3][0] = m_Pos.x;
mat.m[3][1] = m_Pos.y;
mat.m[3][2] = m_Pos.z;
SetTranspose( mat, &matT );
gpd3dDev->SetVertexShaderConstant( 0, &matT, 4 );
// Expected pixel shader constants
//; c0 = light 1 direction
//; c1 = light 2 direction
//; c2 = base blob color
//; c3 = ambient color
D3DVECTOR4 val;
Set(&val, 0.5f, 0.6f, 0.5f, 1.0f );
gpd3dDev->SetPixelShaderConstant( 0, &val, 1 );
Set(&val, 0.5f, 0.4f, 0.5f, 1.0f );
gpd3dDev->SetPixelShaderConstant( 1, &val, 1 );
// Blob color
gpd3dDev->SetPixelShaderConstant( 2, &m_BlobColor, 1 );
// Ambient light
val = m_BlobColor;
val.x *= 0.6f;
val.y *= 0.6f;
val.z *= 0.6f;
gpd3dDev->SetPixelShaderConstant( 3, &val, 1 );
// This could be set in the lava lamp, but we might have blobs with different numbers of vertices.
gpd3dDev->SetIndices( m_pBlobIB, 0 );
gpd3dDev->SetStreamSource( 0, m_pBlobVB, sizeof(BlobVertex) );
gpd3dDev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, m_dwNumVertices,
0, m_dwNumIndices/3 );
}