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

872 lines
27 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// File: Shield.cpp
//
// Copyright 2001 Pipeworks Software
///////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include "xbs_math.h"
#include "xbs_app.h"
#include "qrand.h"
#include "Shield.h"
#include "tex_gen.h"
///////////////////////////////////////////////////////////////////////////////
D3DVECTOR Shield::ms_Pos;
const float SHIELD_ROTATION_RATE = (2.0f);
///////////////////////////////////////////////////////////////////////////////
void Shield::Init()
{
m_RadiusScale = 1.0f;
m_Speed = 1.0f;
}
///////////////////////////////////////////////////////////////////////////////
void Shield::create()
{
}
///////////////////////////////////////////////////////////////////////////////
void Shield::destroy()
{
// Nothing to do.
}
///////////////////////////////////////////////////////////////////////////////
void Shield::render(const D3DMATRIX& mat_wtp)
{
D3DMATRIX transp;
SetTranspose(m_CurMatrix, &transp);
gpd3dDev->SetVertexShaderConstant(0,(CONST void *)&transp,4);
// The ShieldMgr will do the rest of the rendering.
}
///////////////////////////////////////////////////////////////////////////////
void Shield::advanceTime(float fElapsedTime, float fDt)
{
D3DVECTOR4 quat;
float pushout_radius = max(0.0f, (PUSHOUT_START_TIME + PUSHOUT_DELTA - fElapsedTime) * OO_PUSHOUT_DELTA);
pushout_radius = START_PUSHOUT_RADIUS * pushout_radius*pushout_radius;
//MTS if (gApp.getPulseIntensity() > 0.0f) m_Speed += fDt * 1.65f;
m_Speed += fDt * 0.8f;
float theta = fDt * SHIELD_ROTATION_RATE * m_Speed + m_ThetaZero;
m_ThetaZero = theta;
SetQuatFromAxis(m_RotationDir, theta, &quat);
D3DMATRIX mat;
SetRotationFromRHQuat(quat, &mat);
MulMats(m_StartRotation, mat, &m_CurMatrix);
m_CurMatrix._11 *= m_RadiusScale;
m_CurMatrix._12 *= m_RadiusScale;
m_CurMatrix._13 *= m_RadiusScale;
m_CurMatrix._21 *= m_RadiusScale;
m_CurMatrix._22 *= m_RadiusScale;
m_CurMatrix._23 *= m_RadiusScale;
m_CurMatrix._31 *= m_RadiusScale;
m_CurMatrix._32 *= m_RadiusScale;
m_CurMatrix._33 *= m_RadiusScale;
//MTS m_CurMatrix._41 = ms_Pos.x;
//MTS m_CurMatrix._42 = ms_Pos.y;
//MTS m_CurMatrix._43 = ms_Pos.z;
// Adjusted so that the reflection is now stationary as the shield moves around.
m_CurMatrix._41 = ms_Pos.x + m_CurMatrix._11 * (2.0f + pushout_radius);
m_CurMatrix._42 = ms_Pos.y + m_CurMatrix._12 * (2.0f + pushout_radius);
m_CurMatrix._43 = ms_Pos.z + m_CurMatrix._13 * (2.0f);
//MTS bool b_far_side = m_CurCenter.y > ms_Pos.y;
TransformPoint(m_ObjectCenter, m_CurMatrix, &m_CurCenter);
}
///////////////////////////////////////////////////////////////////////////////
void Shield::restart(float radian_extent)
{
float crossing_radian = gApp.fRand01() * 2.09f * Pi;
// Find the constants to make this happen.
// First pick a "peak" orientation.
const float f_RY_ARC = Pi * 1.2f;
bool b_flipped = false;
float rz = gApp.fRand01() * 2.0f * Pi;
float ry = gApp.fRand01() * f_RY_ARC * 2.0f - f_RY_ARC*0.5f;
if (ry > f_RY_ARC * 0.5f)
{
ry += Pi - f_RY_ARC;
b_flipped = true;
}
if (b_flipped)
{
m_ThetaZero = rz + Pi - crossing_radian;
}
else
{
m_ThetaZero = - rz - crossing_radian;
}
//MTS char buf[512];
//MTS sprintf(buf, "Ry=%f, Rz=%f, theta_zero=%f, crossing_radian=%f\n",
//MTS ry, rz, m_ThetaZero, crossing_radian);
//MTS OutputDebugString(buf);
// Rotate around ry
// Rotate around rz
D3DMATRIX mat1, mat2;
SetYRotation(ry, &mat1);
SetZRotation(rz, &mat2);
MulMats(mat1, mat2, &m_StartRotation);
m_RotationDir.x = m_StartRotation._31;
m_RotationDir.y = m_StartRotation._32;
m_RotationDir.z = m_StartRotation._33;
//MTS sprintf(buf, " RotationDir=%+f,%+f,%+f\n",
//MTS m_RotationDir.x, m_RotationDir.y, m_RotationDir.z);
//MTS OutputDebugString(buf);
m_Speed = 0.0f;
advanceTime(0.0f, 0.0f);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ZShield::Init()
{
m_pShieldVB = NULL;
m_pShieldIB = NULL;
m_dwNumVertices = m_dwNumIndices = 0;
m_Speed = 0.0f;
m_Theta = 0.0f;
}
///////////////////////////////////////////////////////////////////////////////
void ZShield::create()
{
}
///////////////////////////////////////////////////////////////////////////////
void ZShield::destroy()
{
#define XBS_RELEASE(a) if (a) a->Release(); a = NULL;
XBS_RELEASE(m_pShieldVB);
XBS_RELEASE(m_pShieldIB);
#undef XBS_RELEASE
m_dwNumVertices = 0;
m_dwNumIndices = 0;
}
///////////////////////////////////////////////////////////////////////////////
void ZShield::render(const D3DMATRIX& mat_wtp)
{
D3DMATRIX transp;
SetTranspose(m_CurMatrix, &transp);
gpd3dDev->SetVertexShaderConstant(0,(CONST void *)&transp,4);
gpd3dDev->SetStreamSource(0, m_pShieldVB, sizeof(ShieldVertex));
gpd3dDev->SetIndices(m_pShieldIB, 0);
gpd3dDev->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, m_dwNumVertices, 0, m_dwNumIndices-2 );
}
///////////////////////////////////////////////////////////////////////////////
void ZShield::advanceTime(float fElapsedTime, float fDt)
{
//MTS if (gApp.getPulseIntensity() > 0.0f) m_Speed += fDt * 1.0f;
m_Speed += fDt * 0.8f;
m_Theta += m_Speed * fDt;
float pushout_radius = max(0.0f, (PUSHOUT_START_TIME + PUSHOUT_DELTA - fElapsedTime) * OO_PUSHOUT_DELTA);
pushout_radius = START_PUSHOUT_RADIUS * pushout_radius*pushout_radius;
SetZRotation(m_Theta, &m_CurMatrix);
m_CurMatrix._41 += m_CurMatrix._11 * (2.0f + pushout_radius);
m_CurMatrix._42 += m_CurMatrix._12 * (2.0f + pushout_radius);
m_CurMatrix._43 += m_CurMatrix._13 * (2.0f);
}
///////////////////////////////////////////////////////////////////////////////
// returns the new start_radian, from bottom (-Pi/2) up.
void ZShield::restart(float start_radian, float end_radian, float outside_radius)
{
destroy();
m_Theta = gApp.fRand01() * 2.0f * Pi;
m_Speed = 0.0f;
// Create the index and vertex buffers.
const int width = 8; // number of panels, one less than the number of vertices
const int height = 6;
const float inside_radius = outside_radius - 0.5f;
const float f_vert_radians = end_radian - start_radian;
const float f_horiz_radians = 1.2f;
int num_verts_per_face = (height+1) * (width+1);
int num_side_verts = 2*2*(height+1) + 2*2*(width+1);
m_dwNumVertices =
2*num_verts_per_face + // top and bottom
num_side_verts; // edges
m_dwNumIndices =
GetNumberOfIndicesForTristripMesh(width, height, false, true) +
GetNumberOfIndicesForTristripMesh(width, height, true, true) +
(height+1)*2 + 2 +
(width+1)*2 + 2 +
(height+1)*2 + 2 +
(width+1)*2 + 1;
gpd3dDev->CreateVertexBuffer( m_dwNumVertices * sizeof(ShieldVertex), 0, 0, 0, &m_pShieldVB);
gpd3dDev->CreateIndexBuffer( m_dwNumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pShieldIB);
// Vertex index is (y*(width+1) + x) + ((inside_face) ? num_verts_per_face+num_side_verts : 0)
// or for the sides num_verts_per_face + 2*(clockwise position from ll) + ((inside_face) ? 1 : 0
ShieldVertex* p_verts;
m_pShieldVB->Lock(0, 0, (BYTE**)&p_verts, 0);
ShieldVertex* pverto = &p_verts[0];
ShieldVertex* pverti = &p_verts[num_verts_per_face+num_side_verts];
float f_left_rad = -0.5f * f_horiz_radians;
float f_right_rad = +0.5f * f_horiz_radians;
float f_top_rad = end_radian;
float f_bottom_rad = start_radian;
float f_horiz_step = (f_right_rad-f_left_rad) / ((float)width);
float f_vert_step = (f_top_rad-f_bottom_rad) / ((float)height);
int i,j;
float f_i, f_j;
for (j=0, f_j=f_bottom_rad; j<=height; j++, f_j+=f_vert_step)
{
float vs,vc;
SinCos(f_j, &vs, &vc);
for (i=0, f_i=f_left_rad; i<=width; i++, f_i+=f_horiz_step)
{
float hs,hc;
SinCos(f_i, &hs, &hc);
D3DVECTOR norm;
Set(&norm, vc*hc, vc*hs, vs);
Set(&pverto->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pverto->normal = norm;
pverto++;
Set(&pverti->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pverti->normal = norm;
Scale(&pverti->normal, -1.0f);
pverti++;
if ((!j) && (i==width)) f_right_rad = f_i; // set it exactly to what we iterate to
}
if (j==height) f_top_rad = f_j; // set it exactly to what we iterate to
}
ShieldVertex* pvert = pverto;
// Fill in the vertices around the edges.
f_i = f_left_rad;
float vs,vc,hs,hc;
// Start at left, move up.
SinCos(f_i, &hs, &hc);
for (j=0, f_j=f_bottom_rad; j<=height; j++, f_j+=f_vert_step)
{
SinCos(f_j, &vs, &vc);
D3DVECTOR norm, side;
Set(&norm, vc*hc, vc*hs, vs);
Set(&side, hs, -hc, 0.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
j = height;
f_j = f_top_rad;
// At UL, move right
for (i=0, f_i=f_left_rad; i<=width; i++, f_i+=f_horiz_step)
{
SinCos(f_i, &hs, &hc);
D3DVECTOR norm, side;
Set(&norm, vc*hc, vc*hs, vs);
Set(&side, -vs*hc, -vs*hs, vc);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// At UR, move down
for (j=height, f_j=f_top_rad; j>=0; j--, f_j-=f_vert_step)
{
if (!j) f_j=f_bottom_rad;
SinCos(f_j, &vs, &vc);
D3DVECTOR norm, side;
Set(&norm, vc*hc, vc*hs, vs);
Set(&side, -hs, hc, 0.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// At LR, move left
for (i=width, f_i=f_right_rad; i>=0; i--, f_i-=f_horiz_step)
{
if (!i) f_i=f_left_rad;
SinCos(f_i, &hs, &hc);
D3DVECTOR norm, side;
Set(&norm, vc*hc, vc*hs, vs);
Set(&side, vs*hc, vs*hs, -vc);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// Done with the vertices!
m_pShieldVB->Unlock();
WORD* p_indices;
m_pShieldIB->Lock(0, 0, (BYTE**)&p_indices, 0);
// Vertex index is (y*(width+1) + x) + ((inside_face) ? num_verts_per_face : 0)
// or for the sides 2*num_verts_per_face + 2*(clockwise position from ll) + ((inside_face) ? 1 : 0
// Outside surface.
int index_num = 0;
index_num += CreateTristripForMesh(&p_indices[index_num], width, height, false, true, 0);
index_num += CreateTristripForMesh(&p_indices[index_num], width, height, true, true, num_verts_per_face+num_side_verts+width, 0, -1);
int vertex_index = num_verts_per_face;
// Sides
for (i=0; i<4; i++)
{
p_indices[index_num++] = (WORD)vertex_index; // first tap of a double-tap
int length = (i&1) ? width : height;
for (j=0; j<=length; j++)
{
p_indices[index_num++] = vertex_index + 0;
p_indices[index_num++] = vertex_index + 1;
vertex_index += 2;
}
if (i<3) p_indices[index_num++] = vertex_index - 1; // double-tap
}
m_pShieldIB->Unlock();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::Init()
{
int i;
for (i = 0; i < MAX_SHIELDS; i++)
{
m_Shields[i].Init();
}
for (int i = 0; i < MAX_ZSHIELDS; i++)
{
m_ZShields[i].Init();
}
m_NumShields = 0;
m_pShieldVB = NULL;
m_pShieldIB = NULL;
m_dwNumVertices = 0;
m_dwNumIndices = 0;
m_dwPShader = 0;
m_dwVShader = 0;
Set(&m_Pos, 0.0f, 0.0f, 0.0f);
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::create()
{
// Make the meshes and stuff.
const int width = 8; // number of panels, one less than the number of vertices
const int height = 6;
const float inside_radius = 13.1f;
const float outside_radius = 14.0f;
const float f_vert_dim = 0.9f;
const float f_horiz_dim = 1.2f;
// Partial sphere surface is made by generating a mesh at x=1.0f, and normalizing the vertices.
m_RadiusScale = 1.0f - 1.2f * (outside_radius-inside_radius) / outside_radius;
m_MidRadius = (inside_radius + outside_radius) * 0.5f;
int num_verts_per_face = (height+1) * (width+1);
int num_side_verts = 2*2*(height+1) + 2*2*(width+1);
m_dwNumVertices =
2*num_verts_per_face + // top and bottom
num_side_verts; // edges
m_dwNumIndices =
GetNumberOfIndicesForTristripMesh(width, height, false, true) +
GetNumberOfIndicesForTristripMesh(width, height, true, true) +
(height+1)*2 + 2 +
(width+1)*2 + 2 +
(height+1)*2 + 2 +
(width+1)*2 + 1;
gpd3dDev->CreateVertexBuffer( m_dwNumVertices * sizeof(ShieldVertex), 0, 0, 0, &m_pShieldVB);
gpd3dDev->CreateIndexBuffer( m_dwNumIndices * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pShieldIB);
// Vertex index is (y*(width+1) + x) + ((inside_face) ? num_verts_per_face+num_side_verts : 0)
// or for the sides num_verts_per_face + 2*(clockwise position from ll) + ((inside_face) ? 1 : 0
ShieldVertex* p_verts;
m_pShieldVB->Lock(0, 0, (BYTE**)&p_verts, 0);
ShieldVertex* pverto = &p_verts[0];
ShieldVertex* pverti = &p_verts[num_verts_per_face+num_side_verts];
float f_left_c = -0.5f * f_horiz_dim;
float f_right_c = +0.5f * f_horiz_dim;
float f_top_c = +0.5f * f_vert_dim;
float f_bottom_c = -0.5f * f_vert_dim;
float f_horiz_step = (f_right_c-f_left_c) / ((float)width);
float f_vert_step = (f_top_c-f_bottom_c) / ((float)height);
int i,j;
float f_i, f_j;
for (j=0, f_j=f_bottom_c; j<=height; j++, f_j+=f_vert_step)
{
for (i=0, f_i=f_left_c; i<=width; i++, f_i+=f_horiz_step)
{
D3DVECTOR norm;
Set(&norm, 1.0f, f_i, f_j);
Normalize(&norm);
Set(&pverto->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pverto->normal = norm;
pverto++;
Set(&pverti->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pverti->normal = norm;
Scale(&pverti->normal, -1.0f);
pverti++;
if ((!j) && (i==width)) f_right_c = f_i; // set it exactly to what we iterate to
}
if (j==height) f_top_c = f_j; // set it exactly to what we iterate to
}
ShieldVertex* pvert = pverto;
// Fill in the vertices around the edges.
f_i = f_left_c;
// Start at left, move up.
for (j=0, f_j=f_bottom_c; j<=height; j++, f_j+=f_vert_step)
{
D3DVECTOR norm, side;
Set(&norm, 1.0f, f_i, f_j);
Normalize(&norm);
Set(&side, 0.0f, -1.0f, 0.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
j = height;
f_j = f_top_c;
// At UL, move right
for (i=0, f_i=f_left_c; i<=width; i++, f_i+=f_horiz_step)
{
D3DVECTOR norm, side;
Set(&norm, 1.0f, f_i, f_j);
Normalize(&norm);
Set(&side, 0.0f, 0.0f, +1.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// At UR, move down
f_i = f_right_c;
for (j=height, f_j=f_top_c; j>=0; j--, f_j-=f_vert_step)
{
if (!j) f_j=f_bottom_c;
D3DVECTOR norm, side;
Set(&norm, 1.0f, f_i, f_j);
Normalize(&norm);
Set(&side, 0.0f, +1.0f, 0.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// At LR, move left
f_j = f_bottom_c;
for (i=width, f_i=f_right_c; i>=0; i--, f_i-=f_horiz_step)
{
if (!i) f_i=f_left_c;
D3DVECTOR norm, side;
Set(&norm, 1.0f, f_i, f_j);
Normalize(&norm);
Set(&side, 0.0f, 0.0f, -1.0f);
Set(&pvert->position, outside_radius*norm.x, outside_radius*norm.y, outside_radius*norm.z);
pvert->normal = side;
pvert++;
Set(&pvert->position, inside_radius*norm.x, inside_radius*norm.y, inside_radius*norm.z);
pvert->normal = side;
pvert++;
}
// Done with the vertices!
m_pShieldVB->Unlock();
WORD* p_indices;
m_pShieldIB->Lock(0, 0, (BYTE**)&p_indices, 0);
// Vertex index is (y*(width+1) + x) + ((inside_face) ? num_verts_per_face : 0)
// or for the sides 2*num_verts_per_face + 2*(clockwise position from ll) + ((inside_face) ? 1 : 0
// Outside surface.
int index_num = 0;
index_num += CreateTristripForMesh(&p_indices[index_num], width, height, false, true, 0);
index_num += CreateTristripForMesh(&p_indices[index_num], width, height, true, true, num_verts_per_face+num_side_verts+width, 0, -1);
int vertex_index = num_verts_per_face;
// Sides
for (i=0; i<4; i++)
{
p_indices[index_num++] = (WORD)vertex_index; // first tap of a double-tap
int length = (i&1) ? width : height;
for (j=0; j<=length; j++)
{
p_indices[index_num++] = vertex_index + 0;
p_indices[index_num++] = vertex_index + 1;
vertex_index += 2;
}
if (i<3) p_indices[index_num++] = vertex_index - 1; // double-tap
}
m_pShieldIB->Unlock();
// Create the shaders.
// Initialize the pixel shaders.
if( m_dwPShader )
{
gpd3dDev->DeletePixelShader( m_dwPShader );
m_dwPShader = 0;
}
#ifndef BINARY_RESOURCE
m_dwPShader = gApp.loadPixelShader("D:\\Shaders\\shield.xpu");
#else // BINARY_RESOURCE
m_dwPShader = gApp.loadPixelShader(g_shield_xpu);
#endif // BINARY_RESOURCE
// Initialize the vertex shaders.
DWORD dwShaderVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // normal
D3DVSD_END()
};
if (m_dwVShader)
{
gpd3dDev->DeleteVertexShader( m_dwVShader );
m_dwVShader = 0;
}
#ifndef BINARY_RESOURCE
m_dwVShader = gApp.loadVertexShader("D:\\Shaders\\shield.xvu", dwShaderVertexDecl);
#else // BINARY_RESOURCE
m_dwVShader = gApp.loadVertexShader(g_shield_xvu, dwShaderVertexDecl);
#endif // BINARY_RESOURCE
for (i=0; i<MAX_SHIELDS; i++) m_Shields[i].create();
for (i=0; i<MAX_ZSHIELDS; i++) m_ZShields[i].create();
restart();
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::destroy()
{
for (int i=0; i<m_NumShields; i++) m_Shields[i].destroy();
m_NumShields = 0;
if (m_dwPShader) gpd3dDev->DeletePixelShader( m_dwPShader );
if (m_dwVShader) gpd3dDev->DeleteVertexShader( m_dwVShader );
m_dwPShader = 0;
m_dwVShader = 0;
#define XBS_RELEASE(a) if (a) a->Release(); a = NULL;
XBS_RELEASE(m_pShieldVB);
XBS_RELEASE(m_pShieldIB);
#undef XBS_RELEASE
m_dwNumVertices = 0;
m_dwNumIndices = 0;
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::render(bool b_far_side)
{
// Set default states
gpd3dDev->SetRenderState( D3DRS_LIGHTING, FALSE );
gpd3dDev->SetRenderState( D3DRS_ZENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
gpd3dDev->SetTexture( 0, gApp.pStaticReflectionCubeMap );
gpd3dDev->SetTexture( 1, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetTexture( 2, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetTexture( 3, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
gpd3dDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 1, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 2, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 3, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
gpd3dDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
gpd3dDev->SetTexture( 0, gApp.pStaticReflectionCubeMap );
gpd3dDev->SetTexture( 1, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetTexture( 2, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetTexture( 3, gApp.pNormalCubeMapHiRes );
gpd3dDev->SetVertexShader( m_dwVShader );
gpd3dDev->SetPixelShader( m_dwPShader );
D3DVECTOR cam_pos, look_dir, look_at;
gApp.theCamera.getCameraPos (&cam_pos);
gApp.theCamera.getCameraLook(&look_at);
Sub(look_at, cam_pos, &look_dir);
//; Expected vertex shaders constants
//; c0-c3 = Transpose of object to world matrix
//; c4-c7 = Transpose of view*projection matrix
//; c8 = some constants, x=0, y=1, z=2, w=0.5
//; c9 = eye location in world space
//; c10 = light pos in world space
// 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,matWTP;
MulMats(gApp.theCamera.matWTC,gApp.theCamera.matProj,&matWTP);
SetTranspose(matWTP,&matFinal);
gpd3dDev->SetVertexShaderConstant(4,(CONST void *)&matFinal,4);
// Constants
D3DVECTOR4 val[4];
Set(&val[0], 0.0f, 1.0f, 2.0f, 0.5f);
// Eye position
Set(&val[1], cam_pos.x, cam_pos.y, cam_pos.z, 0.0f);
// Blob Light position
Set(&val[2],0.f,0.f,0.f,1.f);
// Mood Light position
const D3DVECTOR &mlp = gApp.moodLight.Position;
Set(&val[3],mlp.x,mlp.y,mlp.z,1.f);
gpd3dDev->SetVertexShaderConstant( 8, &val[0], 4 );
// alpha
float f_shading = 0.75f; // 1 = black, 0 = no shading
if (gApp.getElapsedTime() < SHIELD_FADE_IN_START_TIME + SHIELD_FADE_IN_DELTA)
{
f_shading *= (gApp.getElapsedTime() - SHIELD_FADE_IN_START_TIME) * OO_SHIELD_FADE_IN_DELTA;
}
else if (gApp.getElapsedTime() > SHIELD_FADE_OUT_START_TIME)
{
f_shading *= (SHIELD_FADE_OUT_START_TIME + SHIELD_FADE_OUT_DELTA - gApp.getElapsedTime()) * OO_SHIELD_FADE_OUT_DELTA;
}
f_shading = min(1.0f, max(0.0f, f_shading));
Set(&val[0], 0.0f, 0.0f, 0.0f, f_shading); // final alpha is 1.0f - f_shading
// blob light
float f_intensity = gApp.getBlobIntensity() * 2.f;
float fscale = max(0.0f, min(1.0f, (gApp.getElapsedTime()-PUSHOUT_START_TIME) * OO_PUSHOUT_DELTA));
f_intensity *= fscale*fscale;
Set(&val[1], f_intensity, f_intensity, f_intensity, f_intensity);
// Specular coefficient
Set(&val[2], 0.4f,1.f,0.3f,1.f);
gpd3dDev->SetPixelShaderConstant( 0, &val[0], 3 );
gpd3dDev->SetIndices( m_pShieldIB, 0 );
gpd3dDev->SetStreamSource( 0, m_pShieldVB, sizeof(ShieldVertex) );
float shield_dot[MAX_SHIELDS];
int shield_order[MAX_SHIELDS];
int i;
for (i=0; i<m_NumShields; i++)
{
shield_dot[i] = Dot(m_Shields[i].getCenter(), look_dir);
shield_order[i] = i;
}
float f_blob_dot = Dot(m_Pos, look_dir);
for (int j=m_NumShields-1; j>=0; j--)
{
int i = (b_far_side) ? m_NumShields-1-j : j;
if ( (( b_far_side) && (shield_dot[i]>=f_blob_dot)) ||
((!b_far_side) && (shield_dot[i]< f_blob_dot)) )
{
m_Shields[shield_order[i]].render(matWTP);
gpd3dDev->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, m_dwNumVertices, 0, m_dwNumIndices-2 );
}
}
for (int j=m_NumZShields-1; j>=0; j--)
{
if (b_far_side) break;
// Oh, don't bother sorting, see how it looks.
m_ZShields[j].render(matWTP); // sets the object to world transpose transform
}
// Restore the state
gpd3dDev->SetPixelShader( NULL );
gpd3dDev->SetVertexShader( NULL );
gpd3dDev->SetTexture(0, NULL);
gpd3dDev->SetTexture(1, NULL);
gpd3dDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::advanceTime(float fElapsedTime, float fDt)
{
int i;
for (i=0; i<m_NumShields; i++) m_Shields[i].advanceTime(fElapsedTime, fDt);
for (i=0; i<m_NumZShields; i++) m_ZShields[i].advanceTime(fElapsedTime, fDt);
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::restart()
{
Set(&m_Pos, 0.0f, 0.0f, 1.0f);
Shield::sSetCenter(m_Pos);
restartShields();
}
///////////////////////////////////////////////////////////////////////////////
void ShieldMgr::restartShields()
{
float radian_extent = Pi / 6.0f;
float scale = 1.0f;
for (m_NumShields=0; m_NumShields<MAX_SHIELDS; m_NumShields++)
{
m_Shields[m_NumShields].restart(radian_extent);
m_Shields[m_NumShields].setRadiusScale(scale, m_MidRadius);
scale *= m_RadiusScale;
}
float min_rad = -0.45f * Pi;
float max_rad = +0.45f * Pi;
float rad_step = (max_rad-min_rad) / MAX_ZSHIELDS;
for (m_NumZShields=0; m_NumZShields<MAX_ZSHIELDS; m_NumZShields++)
{
float mid_rad = min_rad + rad_step;
m_ZShields[m_NumZShields].restart(min_rad, mid_rad, scale * m_MidRadius);
min_rad = mid_rad;
}
}
///////////////////////////////////////////////////////////////////////////////