729 lines
20 KiB
C++
729 lines
20 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// 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 );
|
|
}
|