/*
**-----------------------------------------------------------------------------
** Name: D3DUtils.cpp
** Purpose: Various D3D utility functions
** Notes:
**
** Copyright (c) 1995 - 1997 by Microsoft, all rights reserved.
**-----------------------------------------------------------------------------
*/
// Note: Must Define D3D_OVERLOADS to get C++ version of D3DMATRIX
#define D3D_OVERLOADS
#include <float.h>
#include <math.h>
#include "d3dutils.h"
const float pi = 3.141592654f;
/*
**-----------------------------------------------------------------------------
** Functions
**-----------------------------------------------------------------------------
*/
/*
**-----------------------------------------------------------------------------
** Name: ZeroMatrix
** Purpose:sets D3D matrix to all 0's
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ZeroMatrix(void)
{
D3DMATRIX ret;
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
ret(i, j) = 0.0f;
}
}
return ret;
} // end ZeroMatrix
/*
**-----------------------------------------------------------------------------
** Name: IdentityMatrix
** Purpose:sets D3D matrix to Identiy (1's on diagonal, zero's elsewhere)
**-----------------------------------------------------------------------------
*/
D3DMATRIX
IdentityMatrix(void)
{
D3DMATRIX ret;
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++){
ret(i, j) = 0.0f;
}
ret(i,i) = 1.0f;
}
return ret;
} // end IdentityMatrix
/*
**-----------------------------------------------------------------------------
** Name: ProjectionMatrix
** Purpose:sets Projection matrix from fov, near and far planes
** Notes:
**1. fov is in radians.
**2. See Blinn, "A Trip Down the Graphics Pipeline" pg 188 for details.
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ProjectionMatrix(const float near_plane,
const float far_plane,
const float fov)
{
floatc, s, Q;
c = (float) cos(fov*0.5);
s = (float) sin(fov*0.5);
Q = s/(1.0f - near_plane/far_plane);
D3DMATRIX ret = ZeroMatrix();
ret(0, 0) = c;
ret(1, 1) = c;
ret(2, 2) = Q;
ret(3, 2) = -Q*near_plane;
ret(2, 3) = s;
return ret;
}// end ProjectionMatrix
/*
**-----------------------------------------------------------------------------
** Name: ViewMatrix
** Purpose:Controls where the camara is.
** Notes:
**1. Note the roll parameter is in radians and rools the viewpoint
**around the viewing direction
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ViewMatrix(const D3DVECTOR& from,
const D3DVECTOR& at,
const D3DVECTOR& world_up,
const float roll)
{
D3DMATRIX view = IdentityMatrix();
D3DVECTOR up, right, view_dir;
view_dir = Normalize(at - from);
right = CrossProduct(world_up, view_dir);
up = CrossProduct(view_dir, right);
right = Normalize(right);
up = Normalize(up);
view(0, 0) = right.x;
view(1, 0) = right.y;
view(2, 0) = right.z;
view(0, 1) = up.x;
view(1, 1) = up.y;
view(2, 1) = up.z;
view(0, 2) = view_dir.x;
view(1, 2) = view_dir.y;
view(2, 2) = view_dir.z;
view(3, 0) = -DotProduct(right, from);
view(3, 1) = -DotProduct(up, from);
view(3, 2) = -DotProduct(view_dir, from);
// Set roll
if (roll != 0.0f) {
view = MatrixMult(RotateZMatrix(-roll), view);
}
return view;
} // end ViewMatrix
/*
**-----------------------------------------------------------------------------
** Name: RotateXMatrix
** Purpose:Rotate matrix about X axis
**-----------------------------------------------------------------------------
*/
D3DMATRIX
RotateXMatrix(const float rads)
{
floatcosine, sine;
cosine = (float) cos(rads);
sine = (float) sin(rads);
D3DMATRIX ret = IdentityMatrix();
ret(1,1) = cosine;
ret(2,2) = cosine;
ret(1,2) = -sine;
ret(2,1) = sine;
return ret;
} // end RotateXMatrix
/*
**-----------------------------------------------------------------------------
** Name: RotateYMatrix
** Purpose:Rotate matrix about Y axis
**-----------------------------------------------------------------------------
*/
D3DMATRIX
RotateYMatrix(const float rads)
{
floatcosine, sine;
cosine = (float) cos(rads);
sine = (float) sin(rads);
D3DMATRIX ret = IdentityMatrix();
ret(0,0) = cosine;
ret(2,2) = cosine;
ret(0,2) = sine;
ret(2,0) = -sine;
return ret;
} // end RotateY
/*
**-----------------------------------------------------------------------------
** Name: RotateZMatrix
** Purpose:Rotate matrix about Z axis
**-----------------------------------------------------------------------------
*/
D3DMATRIX
RotateZMatrix(const float rads)
{
floatcosine, sine;
cosine = (float) cos(rads);
sine = (float) sin(rads);
D3DMATRIX ret = IdentityMatrix();
ret(0,0) = cosine;
ret(1,1) = cosine;
ret(0,1) = -sine;
ret(1,0) = sine;
return ret;
} // end RotateZMatrix
/*
**-----------------------------------------------------------------------------
** Name: TranslateMatrix
** Purpose: Returns matrix to translate by (dx, dy, dz)
**-----------------------------------------------------------------------------
*/
D3DMATRIX
TranslateMatrix(const float dx, const float dy, const float dz)
{
D3DMATRIX ret = IdentityMatrix();
ret(3, 0) = dx;
ret(3, 1) = dy;
ret(3, 2) = dz;
return ret;
} // end TranslateMatrix
/*
**-----------------------------------------------------------------------------
** Name: TranslateMatrix
** Purpose: Returns matrix to translate by v
**-----------------------------------------------------------------------------
*/
D3DMATRIX
TranslateMatrix(const D3DVECTOR& v)
{
D3DMATRIX ret = IdentityMatrix();
ret(3, 0) = v[0];
ret(3, 1) = v[1];
ret(3, 2) = v[2];
return ret;
} // end TranslateMatrix
/*
**-----------------------------------------------------------------------------
** Name: ScaleMatrix
** Purpose: scale matrix (uniform)
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ScaleMatrix(const float size)
{
D3DMATRIX ret = IdentityMatrix();
ret(0, 0) = size;
ret(1, 1) = size;
ret(2, 2) = size;
return ret;
} // end ScaleMatrix
/*
**-----------------------------------------------------------------------------
** Name: ScaleMatrix
** Purpose:scale matrix
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ScaleMatrix(const float a, const float b, const float c)
{
D3DMATRIX ret = IdentityMatrix();
ret(0, 0) = a;
ret(1, 1) = b;
ret(2, 2) = c;
return ret;
} // end ScaleMatrix
/*
**-----------------------------------------------------------------------------
** Name: ScaleMatrix
** Purpose:scale matrix
**-----------------------------------------------------------------------------
*/
D3DMATRIX
ScaleMatrix(const D3DVECTOR& v)
{
D3DMATRIX ret = IdentityMatrix();
ret(0, 0) = v.x;
ret(1, 1) = v.y;
ret(2, 2) = v.z;
return ret;
} // end ScaleMatrix
/*
**-----------------------------------------------------------------------------
** Name: MatrixMult
** Purpose:[C] = [A] * [B]
**-----------------------------------------------------------------------------
*/
D3DMATRIX
MatrixMult(const D3DMATRIX & a, const D3DMATRIX & b)
{
D3DMATRIX ret = ZeroMatrix();
for (int i=0; i<4; i++) {
for (int j=0; j<4; j++) {
for (int k=0; k<4; k++) {
ret(i, j) += a(k, j) * b(i, k);
}
}
}
return ret;
} // end MatrixMult
/*
**-----------------------------------------------------------------------------
** Name: TransformVector
** Purpose:V' = V * [M]
**-----------------------------------------------------------------------------
*/
D3DVECTOR
TransformVector(const D3DVECTOR& v, const D3DMATRIX & m)
{
floathvec[4];
for (int i=0; i<4; i++) {
hvec[i] = 0.0f;
for (int j=0; j<4; j++) {
if (j==3) {
hvec[i] += m(j, i);
} else {
hvec[i] += v[j] * m(j, i);
}
}
}
D3DVECTOR ret(hvec[0]/hvec[3], hvec[1]/hvec[3], hvec[2]/hvec[3]);
return ret;
} // end TransformVector
/*
**-----------------------------------------------------------------------------
** Name: TransformNormal
** Purpose:N' = N * [M]
**-----------------------------------------------------------------------------
*/
D3DVECTOR
TransformNormal(const D3DVECTOR& v, const D3DMATRIX & mat)
{
D3DMATRIXm;
m = MatrixInverse(mat);
m = MatrixTranspose(m);
return TransformVector(v, m);
} // end TransformNormal
/*
**-----------------------------------------------------------------------------
** Name: MatrixInverse
** Purpose:Creates the inverse of a 4x4 matrix
**-----------------------------------------------------------------------------
*/
static voidlubksb(D3DMATRIX & a, int *indx, float *b);
static void ludcmp(D3DMATRIX & a, int *indx, float *d);
D3DMATRIX
MatrixInverse(const D3DMATRIX & m)
{
D3DMATRIXn, y;
inti, j, indx[4];
floatd, col[4];
n = m;
ludcmp(n, indx, &d);
for (j=0; j<4; j++) {
for (i=0; i<4; i++) {
col[i] = 0.0f;
}
col[j] = 1.0f;
lubksb(n, indx, col);
for (i=0; i<4; i++) {
y(i, j) = col[i];
}
}
return y;
} // end MatrixInverse
/*
**-----------------------------------------------------------------------------
** Name: lubksb
** Purpose:backward subsitution
**-----------------------------------------------------------------------------
*/
static void
lubksb(D3DMATRIX & a, int *indx, float *b)
{
inti, j, ii=-1, ip;
floatsum;
for (i=0; i<4; i++) {
ip = indx[i];
sum = b[ip];
b[ip] = b[i];
if (ii>=0) {
for (j=ii; j<=i-1; j++) {
sum -= a(i, j) * b[j];
}
} else if (sum != 0.0) {
ii = i;
}
b[i] = sum;
}
for (i=3; i>=0; i--) {
sum = b[i];
for (j=i+1; j<4; j++) {
sum -= a(i, j) * b[j];
}
b[i] = sum/a(i, i);
}
} // end lubksb
/*
**-----------------------------------------------------------------------------
** Name: ludcmp
** Purpose:LU decomposition
**-----------------------------------------------------------------------------
*/
static void
ludcmp(D3DMATRIX & a, int *indx, float *d)
{
floatvv[4]; /* implicit scale for each row */
floatbig, dum, sum, tmp;
inti, imax, j, k;
*d = 1.0f;
for (i=0; i<4; i++) {
big = 0.0f;
for (j=0; j<4; j++) {
if ((tmp = (float) fabs(a(i, j))) > big) {
big = tmp;
}
}
/*
if (big == 0.0f) {
printf("ludcmp(): singular matrix found...\n");
exit(1);
}
*/
vv[i] = 1.0f/big;
}
for (j=0; j<4; j++) {
for (i=0; i<j; i++) {
sum = a(i, j);
for (k=0; k<i; k++) {
sum -= a(i, k) * a(k, j);
}
a(i, j) = sum;
}
big = 0.0f;
for (i=j; i<4; i++) {
sum = a(i, j);
for (k=0; k<j; k++) {
sum -= a(i, k)*a(k, j);
}
a(i, j) = sum;
if ((dum = vv[i] * (float)fabs(sum)) >= big) {
big = dum;
imax = i;
}
}
if (j != imax) {
for (k=0; k<4; k++) {
dum = a(imax, k);
a(imax, k) = a(j, k);
a(j, k) = dum;
}
*d = -(*d);
vv[imax] = vv[j];
}
indx[j] = imax;
if (a(j, j) == 0.0f) {
a(j, j) = 1.0e-20f; /* can be 0.0 also... */
}
if (j != 3) {
dum = 1.0f/a(j, j);
for (i=j+1; i<4; i++) {
a(i, j) *= dum;
}
}
}
} // end ludcmp
/*
**-----------------------------------------------------------------------------
** Name: Matrix Transpose
** Purpose:[M] = [M]'
**-----------------------------------------------------------------------------
*/
D3DMATRIX
MatrixTranspose(const D3DMATRIX & m)
{
D3DMATRIXret;
inti, j;
for (i=0; i<4; i++) {
for (j=0; j<4; j++) {
ret(i, j) = m(j, i);
}
}
return ret;
} // end MatrixTranspose
/*
Class Methods
*/
/*
**-----------------------------------------------------------------------------
** Name: Light::Light
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
Light::Light(LPDIRECT3D2 lpD3D)
{
memset(&light, 0, sizeof(D3DLIGHT2));
light.dwSize = sizeof(D3DLIGHT2);
lpD3D->CreateLight(&lpD3DLight, NULL);
changed = 1;
// default to no attenuation with distance
light.dvAttenuation0 = 1.0f;
light.dvAttenuation1 = 0.0f;
light.dvAttenuation2 = 0.0f;
// default to no max distance
light.dvRange = D3DLIGHT_RANGE_MAX;
// default to linear ramp from inner to outer cone
light.dvFalloff = 1.0f;
// default to on
light.dwFlags = D3DLIGHT_ACTIVE;
} // end of Light::Light
/*
**-----------------------------------------------------------------------------
** Name: Light::~Light
** Purpose:Destructor
**-----------------------------------------------------------------------------
*/
Light::~Light()
{
if (lpD3DLight) {
lpD3DLight->Release();
lpD3DLight = NULL;
}
} // end Light::~Light
/*
**-----------------------------------------------------------------------------
** Name: PointLight::PointLight
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
PointLight::PointLight(LPDIRECT3D2lpD3D,
const D3DVECTOR&color,
const D3DVECTOR&position) : Light(lpD3D)
{
light.dltType = D3DLIGHT_POINT;
light.dcvColor.r = color[0];
light.dcvColor.g = color[1];
light.dcvColor.b = color[2];
light.dvPosition.x = position[0];
light.dvPosition.y = position[1];
light.dvPosition.z = position[2];
changed = 1;
} // end PointLight::PointLight
/*
**-----------------------------------------------------------------------------
** Name: SpotLight::SpotLight
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
SpotLight::SpotLight(LPDIRECT3D2lpD3D,
const D3DVECTOR&color,
const D3DVECTOR&position,
const D3DVECTOR&direction,
const floatumbra_angle,
const floatpenumbra_angle) : Light(lpD3D)
{
light.dltType = D3DLIGHT_SPOT;
light.dcvColor.r = color[0];
light.dcvColor.g = color[1];
light.dcvColor.b = color[2];
light.dvPosition.x = position[0];
light.dvPosition.y = position[1];
light.dvPosition.z = position[2];
light.dvDirection.x = direction[0];
light.dvDirection.y = direction[1];
light.dvDirection.z = direction[2];
light.dvTheta = umbra_angle;
light.dvPhi = penumbra_angle;
changed = 1;
} // end of SpotLight::SpotLight
/*
**-----------------------------------------------------------------------------
** Name: DirectionalLight::DirectionalLight
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
DirectionalLight::DirectionalLight(LPDIRECT3D2lpD3D,
const D3DVECTOR&color,
const D3DVECTOR&direction) : Light(lpD3D)
{
light.dltType = D3DLIGHT_DIRECTIONAL;
light.dcvColor.r = color[0];
light.dcvColor.g = color[1];
light.dcvColor.b = color[2];
light.dvDirection.x = direction[0];
light.dvDirection.y = direction[1];
light.dvDirection.z = direction[2];
changed = 1;
}// end of DirectionalLight::DirectionalLight
/*
**-----------------------------------------------------------------------------
** Name: ParallelLight::ParallelLight
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
ParallelPointLight::ParallelPointLight(LPDIRECT3D2lpD3D,
const D3DVECTOR&color,
const D3DVECTOR&position) : Light(lpD3D)
{
light.dltType = D3DLIGHT_PARALLELPOINT;
light.dcvColor.r = color[0];
light.dcvColor.g = color[1];
light.dcvColor.b = color[2];
light.dvPosition.x = position[0];
light.dvPosition.y = position[1];
light.dvPosition.z = position[2];
changed = 1;
} // end of ParallelPointLight::ParallelPointLight constructor
/*
**-----------------------------------------------------------------------------
** Name: Material::Material
** Purpose:Constructor
**-----------------------------------------------------------------------------
*/
Material::Material(LPDIRECT3D2 lpD3D, LPDIRECT3DDEVICE2 lpDev)
{
memset(&Mat, 0, sizeof(D3DMATERIAL));
Mat.dwSize = sizeof(D3DMATERIAL);
// leave the default material black
Mat.dwRampSize = 16;
Mat.diffuse.a = 1.0f;
lpD3D->CreateMaterial(&lpMat, NULL);
lpMat->SetMaterial(&Mat);
lpMat->GetHandle(lpDev, &hMat);
changed = 1;
Set();
} // end of Material::Material
/*
**-----------------------------------------------------------------------------
** Name: Material::~Material
** Purpose:Destructor
**-----------------------------------------------------------------------------
*/
Material::~Material()
{
if (lpMat) {
lpMat->Release();
lpMat = NULL;
}
} // end of Material::~Material
/*
**-----------------------------------------------------------------------------
** Name: rnd
** Purpose:Returns a random number (float) in the range [0.0 - 1.0]
**-----------------------------------------------------------------------------
*/
float
rnd(void)
{
return float(rand())/RAND_MAX;
}// end of rnd()
/*
**-----------------------------------------------------------------------------
** end of File
**-----------------------------------------------------------------------------
*/