938 lines
28 KiB
C++
938 lines
28 KiB
C++
//-----------------------------------------------------------------------------
|
|
// File: objects.cpp
|
|
//
|
|
// Desc: Creates command lists for pipe primitive objects
|
|
//
|
|
// Copyright (c) 1994-2000 Microsoft Corporation
|
|
//-----------------------------------------------------------------------------
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OBJECT constructor
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
OBJECT::OBJECT( IDirect3DDevice8* pd3dDevice )
|
|
{
|
|
m_pd3dDevice = pd3dDevice;
|
|
m_pVB = NULL;
|
|
m_dwNumTriangles = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OBJECT destructor
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
OBJECT::~OBJECT( )
|
|
{
|
|
SAFE_RELEASE( m_pVB );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: Draw
|
|
// Desc: - Draw the object by calling its display list
|
|
//-----------------------------------------------------------------------------
|
|
void OBJECT::Draw( D3DXMATRIX* pWorldMat )
|
|
{
|
|
if( m_pVB )
|
|
{
|
|
m_pd3dDevice->SetTransform( D3DTS_WORLD, pWorldMat );
|
|
|
|
m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX );
|
|
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(D3DVERTEX) );
|
|
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
|
|
0, m_dwNumTriangles );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: PIPE_OBJECT constructors
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
PIPE_OBJECT::PIPE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float len ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, len, 0.0f, 0.0f );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
PIPE_OBJECT::PIPE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float len,
|
|
float s_start, float s_end ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, len, s_start, s_end );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: ELBOW_OBJECT constructors
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
ELBOW_OBJECT::ELBOW_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
|
|
int notch ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, notch, 0.0f, 0.0f );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
ELBOW_OBJECT::ELBOW_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, int notch, float s_start, float s_end ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, notch, s_start, s_end );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BALLJOINT_OBJECT constructor
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
BALLJOINT_OBJECT::BALLJOINT_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
|
|
int notch, float s_start, float s_end ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, notch, s_start, s_end );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SPHERE_OBJECT constructors
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
SPHERE_OBJECT::SPHERE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float radius ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, radius, 0.0f, 0.0f );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
SPHERE_OBJECT::SPHERE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
|
|
float radius, float s_start, float s_end ) : OBJECT(pd3dDevice)
|
|
{
|
|
Build( pBuildInfo, radius, s_start, s_end );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc: rotate circle around x-axis, with edge attached to anchor
|
|
//-----------------------------------------------------------------------------
|
|
static void TransformCircle( float angle, D3DXVECTOR3 *inPoint, D3DXVECTOR3 *outPoint,
|
|
int num, D3DXVECTOR3 *anchor )
|
|
{
|
|
D3DXMATRIX matrix1, matrix2, matrix3;
|
|
int i;
|
|
|
|
// translate anchor point to origin
|
|
D3DXMatrixIdentity( &matrix1 );
|
|
D3DXMatrixTranslation( &matrix1, -anchor->x, -anchor->y, -anchor->z );
|
|
|
|
// rotate by angle, cw around x-axis
|
|
D3DXMatrixIdentity( &matrix2 );
|
|
D3DXMatrixRotationYawPitchRoll( &matrix2, 0.0f, angle, 0.0f );
|
|
|
|
// concat these 2
|
|
D3DXMatrixMultiply( &matrix3, &matrix1, &matrix2 );
|
|
|
|
// translate back
|
|
D3DXMatrixIdentity( &matrix2 );
|
|
D3DXMatrixTranslation( &matrix2, anchor->x, anchor->y, anchor->z );
|
|
|
|
// concat these 2
|
|
D3DXMatrixMultiply( &matrix1, &matrix3, &matrix2 );
|
|
|
|
// transform all the points, + center
|
|
for( i = 0; i < num; i ++, outPoint++, inPoint++ )
|
|
{
|
|
D3DXVECTOR4 tmp;
|
|
D3DXVec3Transform( &tmp, inPoint, &matrix1 );
|
|
outPoint->x = tmp.x;
|
|
outPoint->y = tmp.y;
|
|
outPoint->z = tmp.z;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
static void CalcNormals( D3DXVECTOR3 *p, D3DXVECTOR3 *n, D3DXVECTOR3 *center,
|
|
int num )
|
|
{
|
|
D3DXVECTOR3 vec;
|
|
int i;
|
|
|
|
for( i = 0; i < num; i ++, n++, p++ )
|
|
{
|
|
n->x = p->x - center->x;
|
|
n->y = p->y - center->y;
|
|
n->z = p->z - center->z;
|
|
D3DXVec3Normalize( n, n );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
#define CACHE_SIZE 100
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BuildElbow
|
|
// Desc: - builds elbows, by rotating a circle in the y=r plane
|
|
// centered at (0,r,-r), CW around the x-axis at anchor pt.
|
|
// (r = radius of the circle)
|
|
// - rotation is 90.0 degrees, ending at circle in z=0 plane,
|
|
// centered at origin.
|
|
// - in order to 'mate' texture coords with the cylinders
|
|
// generated with glu, we generate 4 elbows, each corresponding
|
|
// to the 4 possible CW 90 degree orientations of the start point
|
|
// for each circle.
|
|
// - We call this start point the 'notch'. If we characterize
|
|
// each notch by the axis it points down in the starting and
|
|
// ending circles of the elbow, then we get the following axis
|
|
// pairs for our 4 notches:
|
|
// - +z,+y
|
|
// - +x,+x
|
|
// - -z,-y
|
|
// - -x,-x
|
|
// Since the start of the elbow always points down +y, the 4
|
|
// start notches give all possible 90.0 degree orientations
|
|
// around y-axis.
|
|
// - We can keep track of the current 'notch' vector to provide
|
|
// proper mating between primitives.
|
|
// - Each circle of points is described CW from the start point,
|
|
// assuming looking down the +y axis(+y direction).
|
|
// - texture 's' starts at 0.0, and goes to 2.0*r/divSize at
|
|
// end of the elbow. (Then a short pipe would start with this
|
|
// 's', and run it to 1.0).
|
|
//-----------------------------------------------------------------------------
|
|
void ELBOW_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch,
|
|
float s_start, float s_end )
|
|
{
|
|
int stacks, slices;
|
|
float angle, startAng;
|
|
int numPoints;
|
|
float s_delta;
|
|
D3DXVECTOR3 pi[CACHE_SIZE]; // initial row of points + center
|
|
D3DXVECTOR3 p0[CACHE_SIZE]; // 2 rows of points
|
|
D3DXVECTOR3 p1[CACHE_SIZE];
|
|
D3DXVECTOR3 n0[CACHE_SIZE]; // 2 rows of normals
|
|
D3DXVECTOR3 n1[CACHE_SIZE];
|
|
float tex_t[CACHE_SIZE];// 't' texture coords
|
|
float* curTex_t;
|
|
float tex_s[2]; // 's' texture coords
|
|
D3DXVECTOR3 center; // center of circle
|
|
D3DXVECTOR3 anchor; // where circle is anchored
|
|
D3DXVECTOR3* pA;
|
|
D3DXVECTOR3* pB;
|
|
D3DXVECTOR3* nA;
|
|
D3DXVECTOR3* nB;
|
|
|
|
D3DXVECTOR3* pTA;
|
|
D3DXVECTOR3* pTB;
|
|
D3DXVECTOR3* nTA;
|
|
D3DXVECTOR3* nTB;
|
|
|
|
int i,j;
|
|
IPOINT2D* texRep = pBuildInfo->m_texRep;
|
|
float radius = pBuildInfo->m_radius;
|
|
|
|
slices = pBuildInfo->m_nSlices;
|
|
stacks = slices / 2;
|
|
|
|
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
|
|
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
|
|
|
|
s_delta = s_end - s_start;
|
|
|
|
// calculate 't' texture coords
|
|
if( texRep )
|
|
{
|
|
for( i = 0; i <= slices; i ++ )
|
|
{
|
|
tex_t[i] = (float) i * texRep->y / slices;
|
|
}
|
|
}
|
|
|
|
numPoints = slices + 1;
|
|
|
|
// starting angle increment 90.0 degrees each time
|
|
startAng = notch * PI / 2;
|
|
|
|
// calc initial circle of points for circle centered at 0,r,-r
|
|
// points start at (0,r,0), and rotate circle CCW
|
|
|
|
for( i = 0; i <= slices; i ++ )
|
|
{
|
|
angle = startAng + (2 * PI * i / slices);
|
|
pi[i].x = radius * (float) sin(angle);
|
|
pi[i].y = radius;
|
|
// translate z by -r, cuz these cos calcs are for circle at origin
|
|
pi[i].z = radius * (float) cos(angle) - radius;
|
|
}
|
|
|
|
// center point, tacked onto end of circle of points
|
|
pi[i].x = 0.0f;
|
|
pi[i].y = radius;
|
|
pi[i].z = -radius;
|
|
center = pi[i];
|
|
|
|
// anchor point
|
|
anchor.x = anchor.z = 0.0f;
|
|
anchor.y = radius;
|
|
|
|
// calculate initial normals
|
|
CalcNormals( pi, n0, ¢er, numPoints );
|
|
|
|
// initial 's' texture coordinate
|
|
tex_s[0] = s_start;
|
|
|
|
// setup pointers
|
|
pA = pi;
|
|
pB = p0;
|
|
nA = n0;
|
|
nB = n1;
|
|
|
|
DWORD dwNumQuadStripsPerStack = numPoints - 1;
|
|
DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
|
|
m_dwNumTriangles = dwNumQuadStrips * 2;
|
|
DWORD dwNumVertices = m_dwNumTriangles * 3;
|
|
if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
|
|
D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
|
|
D3DPOOL_MANAGED, &m_pVB ) ) )
|
|
return;
|
|
|
|
D3DVERTEX* vQuad;
|
|
D3DVERTEX* vCurQuad;
|
|
vQuad = new D3DVERTEX[dwNumVertices];
|
|
ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
|
|
|
|
vCurQuad = vQuad;
|
|
for( i = 1; i <= stacks; i ++ )
|
|
{
|
|
// ! this angle must be negative, for correct vertex orientation !
|
|
angle = - 0.5f * PI * i / stacks;
|
|
|
|
// transform to get next circle of points + center
|
|
TransformCircle( angle, pi, pB, numPoints+1, &anchor );
|
|
|
|
// calculate normals
|
|
center = pB[numPoints];
|
|
CalcNormals( pB, nB, ¢er, numPoints );
|
|
|
|
// calculate next 's' texture coord
|
|
tex_s[1] = (float) s_start + s_delta * i / stacks;
|
|
|
|
curTex_t = tex_t;
|
|
pTA = pA;
|
|
pTB = pB;
|
|
nTA = nA;
|
|
nTB = nB;
|
|
|
|
for (j = 0; j < numPoints; j++)
|
|
{
|
|
vCurQuad->p = *pTA++;
|
|
vCurQuad->n = *nTA++;
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) tex_s[0];
|
|
vCurQuad->tv = (float) *curTex_t;
|
|
}
|
|
vCurQuad++;
|
|
|
|
vCurQuad->p = *pTB++;
|
|
vCurQuad->n = *nTB++;
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) tex_s[1];
|
|
vCurQuad->tv = (float) *curTex_t++;
|
|
}
|
|
vCurQuad++;
|
|
}
|
|
|
|
// reset pointers
|
|
pA = pB;
|
|
nA = nB;
|
|
pB = (pB == p0) ? p1 : p0;
|
|
nB = (nB == n0) ? n1 : n0;
|
|
tex_s[0] = tex_s[1];
|
|
}
|
|
|
|
D3DVERTEX* v;
|
|
DWORD dwCurQuad = 0;
|
|
DWORD dwVert = 0;
|
|
|
|
m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
|
|
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
for (i = 0; i < numPoints; i++)
|
|
{
|
|
if( i==0 )
|
|
{
|
|
dwCurQuad++;
|
|
continue;
|
|
}
|
|
|
|
// Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
|
|
DWORD dwTemp = dwCurQuad*2-1;
|
|
|
|
v[dwVert++] = vQuad[dwTemp];
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
dwCurQuad++;
|
|
}
|
|
}
|
|
|
|
m_pVB->Unlock();
|
|
|
|
SAFE_DELETE_ARRAY( vQuad );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BuildBallJoint
|
|
// Desc: - These are very similar to the elbows, in that the starting
|
|
// and ending positions are almost identical. The difference
|
|
// here is that the circles in the sweep describe a sphere as
|
|
// they are rotated.
|
|
//-----------------------------------------------------------------------------
|
|
void BALLJOINT_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch,
|
|
float s_start, float s_end )
|
|
{
|
|
float ballRadius;
|
|
float angle, delta_a, startAng, theta;
|
|
int numPoints;
|
|
float s_delta;
|
|
D3DXVECTOR3 pi0[CACHE_SIZE]; // 2 circles of untransformed points
|
|
D3DXVECTOR3 pi1[CACHE_SIZE];
|
|
D3DXVECTOR3 p0[CACHE_SIZE]; // 2 rows of transformed points
|
|
D3DXVECTOR3 p1[CACHE_SIZE];
|
|
D3DXVECTOR3 n0[CACHE_SIZE]; // 2 rows of normals
|
|
D3DXVECTOR3 n1[CACHE_SIZE];
|
|
float r[CACHE_SIZE]; // radii of the circles
|
|
float tex_t[CACHE_SIZE];// 't' texture coords
|
|
float tex_s[2]; // 's' texture coords
|
|
D3DXVECTOR3 center; // center of circle
|
|
D3DXVECTOR3 anchor; // where circle is anchored
|
|
D3DXVECTOR3 *pA, *pB, *nA, *nB;
|
|
float* curTex_t;
|
|
D3DXVECTOR3* pTA;
|
|
D3DXVECTOR3* pTB;
|
|
D3DXVECTOR3* nTA;
|
|
D3DXVECTOR3* nTB;
|
|
int i, j, k;
|
|
int stacks, slices;
|
|
IPOINT2D *texRep = pBuildInfo->m_texRep;
|
|
float radius = pBuildInfo->m_radius;
|
|
|
|
slices = pBuildInfo->m_nSlices;
|
|
stacks = slices;
|
|
|
|
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
|
|
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
|
|
|
|
// calculate the radii for each circle in the sweep, where
|
|
// r[i] = y = sin(angle)/r
|
|
|
|
angle = PI / 4; // first radius always at 45.0 degrees
|
|
delta_a = (PI / 2.0f) / stacks;
|
|
|
|
ballRadius = ROOT_TWO * radius;
|
|
for( i = 0; i <= stacks; i ++, angle += delta_a )
|
|
{
|
|
r[i] = (float) sin(angle) * ballRadius;
|
|
}
|
|
|
|
// calculate 't' texture coords
|
|
for( i = 0; i <= slices; i ++ )
|
|
{
|
|
tex_t[i] = (float) i * texRep->y / slices;
|
|
}
|
|
|
|
s_delta = s_end - s_start;
|
|
|
|
numPoints = slices + 1;
|
|
|
|
// unlike the elbow, the center for the ball joint is constant
|
|
center.x = center.y = 0.0f;
|
|
center.z = -radius;
|
|
|
|
// starting angle along circle, increment 90.0 degrees each time
|
|
startAng = notch * PI / 2;
|
|
|
|
// calc initial circle of points for circle centered at 0,r,-r
|
|
// points start at (0,r,0), and rotate circle CCW
|
|
|
|
delta_a = 2 * PI / slices;
|
|
for( i = 0, theta = startAng; i <= slices; i ++, theta += delta_a )
|
|
{
|
|
pi0[i].x = r[0] * (float) sin(theta);
|
|
pi0[i].y = radius;
|
|
// translate z by -r, cuz these cos calcs are for circle at origin
|
|
pi0[i].z = r[0] * (float) cos(theta) - r[0];
|
|
}
|
|
|
|
// anchor point
|
|
anchor.x = anchor.z = 0.0f;
|
|
anchor.y = radius;
|
|
|
|
// calculate initial normals
|
|
CalcNormals( pi0, n0, ¢er, numPoints );
|
|
|
|
// initial 's' texture coordinate
|
|
tex_s[0] = s_start;
|
|
|
|
// setup pointers
|
|
pA = pi0; // circles of transformed points
|
|
pB = p0;
|
|
nA = n0; // circles of transformed normals
|
|
nB = n1;
|
|
|
|
DWORD dwNumQuadStripsPerStack = numPoints - 1;
|
|
DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
|
|
m_dwNumTriangles = dwNumQuadStrips * 2;
|
|
DWORD dwNumVertices = m_dwNumTriangles * 3;
|
|
if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
|
|
D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
|
|
D3DPOOL_MANAGED, &m_pVB ) ) )
|
|
return;
|
|
|
|
D3DVERTEX* vQuad;
|
|
D3DVERTEX* vCurQuad;
|
|
vQuad = new D3DVERTEX[dwNumVertices];
|
|
ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
|
|
|
|
vCurQuad = vQuad;
|
|
for( i = 1; i <= stacks; i ++ )
|
|
{
|
|
// ! this angle must be negative, for correct vertex orientation !
|
|
angle = - 0.5f * PI * i / stacks;
|
|
|
|
for( k = 0, theta = startAng; k <= slices; k ++, theta+=delta_a )
|
|
{
|
|
pi1[k].x = r[i] * (float) sin(theta);
|
|
pi1[k].y = radius;
|
|
// translate z by -r, cuz calcs are for circle at origin
|
|
pi1[k].z = r[i] * (float) cos(theta) - r[i];
|
|
}
|
|
|
|
// transform to get next circle of points + center
|
|
TransformCircle( angle, pi1, pB, numPoints, &anchor );
|
|
|
|
// calculate normals
|
|
CalcNormals( pB, nB, ¢er, numPoints );
|
|
|
|
// calculate next 's' texture coord
|
|
tex_s[1] = (float) s_start + s_delta * i / stacks;
|
|
|
|
curTex_t = tex_t;
|
|
pTA = pA;
|
|
pTB = pB;
|
|
nTA = nA;
|
|
nTB = nB;
|
|
|
|
for (j = 0; j < numPoints; j++)
|
|
{
|
|
vCurQuad->p = *pTA++;
|
|
vCurQuad->n = *nTA++;
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) tex_s[0];
|
|
vCurQuad->tv = (float) *curTex_t;
|
|
}
|
|
vCurQuad++;
|
|
|
|
vCurQuad->p = *pTB++;
|
|
vCurQuad->n = *nTB++;
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) tex_s[1];
|
|
vCurQuad->tv = (float) *curTex_t++;
|
|
}
|
|
vCurQuad++;
|
|
}
|
|
|
|
// reset pointers
|
|
pA = pB;
|
|
nA = nB;
|
|
pB = (pB == p0) ? p1 : p0;
|
|
nB = (nB == n0) ? n1 : n0;
|
|
tex_s[0] = tex_s[1];
|
|
}
|
|
|
|
D3DVERTEX* v;
|
|
DWORD dwCurQuad = 0;
|
|
DWORD dwVert = 0;
|
|
|
|
m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
|
|
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
for (i = 0; i < numPoints; i++)
|
|
{
|
|
if( i==0 )
|
|
{
|
|
dwCurQuad++;
|
|
continue;
|
|
}
|
|
|
|
// Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
|
|
DWORD dwTemp = dwCurQuad*2-1;
|
|
|
|
v[dwVert++] = vQuad[dwTemp];
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
dwCurQuad++;
|
|
}
|
|
}
|
|
|
|
m_pVB->Unlock();
|
|
|
|
SAFE_DELETE_ARRAY( vQuad );
|
|
}
|
|
|
|
// 'glu' routines
|
|
#ifdef _EXTENSIONS_
|
|
#define COS cosf
|
|
#define SIN sinf
|
|
#define SQRT sqrtf
|
|
#else
|
|
#define COS cos
|
|
#define SIN sin
|
|
#define SQRT sqrt
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: BuildCylinder
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void PIPE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, float length, float s_start,
|
|
float s_end )
|
|
{
|
|
int stacks, slices;
|
|
int i,j;
|
|
float sinCache[CACHE_SIZE];
|
|
float cosCache[CACHE_SIZE];
|
|
float sinCache2[CACHE_SIZE];
|
|
float cosCache2[CACHE_SIZE];
|
|
float angle;
|
|
float zNormal;
|
|
float s_delta;
|
|
float zHigh, zLow;
|
|
IPOINT2D *texRep = pBuildInfo->m_texRep;
|
|
float radius = pBuildInfo->m_radius;
|
|
|
|
slices = pBuildInfo->m_nSlices;
|
|
stacks = (int) SS_ROUND_UP( (length/pBuildInfo->m_divSize) * (float)slices) ;
|
|
|
|
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
|
|
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
|
|
zNormal = 0.0f;
|
|
|
|
s_delta = s_end - s_start;
|
|
|
|
for (i = 0; i < slices; i++)
|
|
{
|
|
angle = 2 * PI * i / slices;
|
|
sinCache2[i] = (float) SIN(angle);
|
|
cosCache2[i] = (float) COS(angle);
|
|
sinCache[i] = (float) SIN(angle);
|
|
cosCache[i] = (float) COS(angle);
|
|
}
|
|
|
|
sinCache[slices] = sinCache[0];
|
|
cosCache[slices] = cosCache[0];
|
|
sinCache2[slices] = sinCache2[0];
|
|
cosCache2[slices] = cosCache2[0];
|
|
|
|
DWORD dwNumQuadStripsPerStack = slices;
|
|
DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
|
|
m_dwNumTriangles = dwNumQuadStrips * 2;
|
|
DWORD dwNumVertices = m_dwNumTriangles * 3;
|
|
if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
|
|
D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
|
|
D3DPOOL_MANAGED, &m_pVB ) ) )
|
|
return;
|
|
|
|
D3DVERTEX* vQuad;
|
|
D3DVERTEX* vCurQuad;
|
|
vQuad = new D3DVERTEX[dwNumVertices];
|
|
ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
|
|
|
|
vCurQuad = vQuad;
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
zLow = j * length / stacks;
|
|
zHigh = (j + 1) * length / stacks;
|
|
|
|
for (i = 0; i <= slices; i++)
|
|
{
|
|
vCurQuad->p = D3DXVECTOR3( radius * sinCache[i], radius * cosCache[i], zLow );
|
|
vCurQuad->n = D3DXVECTOR3( sinCache2[i], cosCache2[i], zNormal );
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) s_start + s_delta * j / stacks;
|
|
vCurQuad->tv = (float) i * texRep->y / slices;
|
|
}
|
|
vCurQuad++;
|
|
|
|
vCurQuad->p = D3DXVECTOR3( radius * sinCache[i], radius * cosCache[i], zHigh );
|
|
vCurQuad->n = D3DXVECTOR3( sinCache2[i], cosCache2[i], zNormal );
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) s_start + s_delta*(j+1) / stacks;
|
|
vCurQuad->tv = (float) i * texRep->y / slices;
|
|
}
|
|
vCurQuad++;
|
|
}
|
|
}
|
|
|
|
D3DVERTEX* v;
|
|
DWORD dwCurQuad = 0;
|
|
DWORD dwVert = 0;
|
|
|
|
m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
|
|
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
for (i = 0; i <= slices; i++)
|
|
{
|
|
if( i==0 )
|
|
{
|
|
dwCurQuad++;
|
|
continue;
|
|
}
|
|
// Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
|
|
DWORD dwTemp = dwCurQuad*2-1;
|
|
|
|
v[dwVert++] = vQuad[dwTemp];
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
dwCurQuad++;
|
|
}
|
|
}
|
|
|
|
m_pVB->Unlock();
|
|
|
|
SAFE_DELETE_ARRAY( vQuad );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: pipeSphere
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void SPHERE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, float radius,
|
|
float s_start, float s_end)
|
|
{
|
|
int i,j;
|
|
float sinCache1a[CACHE_SIZE];
|
|
float cosCache1a[CACHE_SIZE];
|
|
float sinCache2a[CACHE_SIZE];
|
|
float cosCache2a[CACHE_SIZE];
|
|
float sinCache1b[CACHE_SIZE];
|
|
float cosCache1b[CACHE_SIZE];
|
|
float sinCache2b[CACHE_SIZE];
|
|
float cosCache2b[CACHE_SIZE];
|
|
float angle;
|
|
float s_delta;
|
|
int stacks, slices;
|
|
IPOINT2D *texRep = pBuildInfo->m_texRep;
|
|
|
|
slices = pBuildInfo->m_nSlices;
|
|
stacks = slices;
|
|
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
|
|
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
|
|
|
|
// invert sense of s - it seems the glu sphere is not built similarly
|
|
// to the glu cylinder
|
|
// (this probably means stacks don't grow along +z - check it out)
|
|
s_delta = s_start;
|
|
s_start = s_end;
|
|
s_end = s_delta;
|
|
|
|
s_delta = s_end - s_start;
|
|
|
|
// Cache is the vertex locations cache
|
|
// Cache2 is the various normals at the vertices themselves
|
|
for (i = 0; i < slices; i++)
|
|
{
|
|
angle = 2 * PI * i / slices;
|
|
sinCache1a[i] = (float) SIN(angle);
|
|
cosCache1a[i] = (float) COS(angle);
|
|
sinCache2a[i] = sinCache1a[i];
|
|
cosCache2a[i] = cosCache1a[i];
|
|
}
|
|
|
|
for (j = 0; j <= stacks; j++)
|
|
{
|
|
angle = PI * j / stacks;
|
|
sinCache2b[j] = (float) SIN(angle);
|
|
cosCache2b[j] = (float) COS(angle);
|
|
sinCache1b[j] = radius * (float) SIN(angle);
|
|
cosCache1b[j] = radius * (float) COS(angle);
|
|
}
|
|
|
|
// Make sure it comes to a point
|
|
sinCache1b[0] = 0.0f;
|
|
sinCache1b[stacks] = 0.0f;
|
|
|
|
sinCache1a[slices] = sinCache1a[0];
|
|
cosCache1a[slices] = cosCache1a[0];
|
|
sinCache2a[slices] = sinCache2a[0];
|
|
cosCache2a[slices] = cosCache2a[0];
|
|
|
|
int start, finish;
|
|
float zLow, zHigh;
|
|
float sintemp1, sintemp2, sintemp3, sintemp4;
|
|
float costemp3, costemp4;
|
|
|
|
start = 0;
|
|
finish = stacks;
|
|
|
|
DWORD dwNumQuadStripsPerStack = slices;
|
|
DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * (finish-start);
|
|
m_dwNumTriangles = dwNumQuadStrips * 2;
|
|
DWORD dwNumVertices = m_dwNumTriangles * 3;
|
|
if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
|
|
D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
|
|
D3DPOOL_MANAGED, &m_pVB ) ) )
|
|
return;
|
|
|
|
D3DVERTEX* vQuad;
|
|
D3DVERTEX* vCurQuad;
|
|
vQuad = new D3DVERTEX[dwNumVertices];
|
|
ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
|
|
|
|
vCurQuad = vQuad;
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
zLow = cosCache1b[j];
|
|
zHigh = cosCache1b[j+1];
|
|
sintemp1 = sinCache1b[j];
|
|
sintemp2 = sinCache1b[j+1];
|
|
|
|
sintemp3 = sinCache2b[j+1];
|
|
costemp3 = cosCache2b[j+1];
|
|
sintemp4 = sinCache2b[j];
|
|
costemp4 = cosCache2b[j];
|
|
|
|
for (i = 0; i <= slices; i++)
|
|
{
|
|
|
|
vCurQuad->p = D3DXVECTOR3( sintemp2 * sinCache1a[i], sintemp2 * cosCache1a[i], zHigh );
|
|
vCurQuad->n = D3DXVECTOR3( sinCache2a[i] * sintemp3, cosCache2a[i] * sintemp3, costemp3 );
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) s_start + s_delta*(j+1) / stacks;
|
|
vCurQuad->tv = (float) i * texRep->y / slices;
|
|
}
|
|
vCurQuad++;
|
|
|
|
vCurQuad->p = D3DXVECTOR3( sintemp1 * sinCache1a[i], sintemp1 * cosCache1a[i], zLow );
|
|
vCurQuad->n = D3DXVECTOR3( sinCache2a[i] * sintemp4, cosCache2a[i] * sintemp4, costemp4 );
|
|
if( texRep )
|
|
{
|
|
vCurQuad->tu = (float) s_start + s_delta * j / stacks;
|
|
vCurQuad->tv = (float) i * texRep->y / slices;
|
|
}
|
|
vCurQuad++;
|
|
|
|
}
|
|
}
|
|
|
|
D3DVERTEX* v;
|
|
DWORD dwCurQuad = 0;
|
|
DWORD dwVert = 0;
|
|
|
|
m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
|
|
|
|
for (j = 0; j < stacks; j++)
|
|
{
|
|
for (i = 0; i <= slices; i++)
|
|
{
|
|
if( i==0 )
|
|
{
|
|
dwCurQuad++;
|
|
continue;
|
|
}
|
|
// Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
|
|
DWORD dwTemp = dwCurQuad*2-1;
|
|
|
|
v[dwVert++] = vQuad[dwTemp];
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
v[dwVert++] = vQuad[dwTemp-1];
|
|
v[dwVert++] = vQuad[dwTemp+1];
|
|
v[dwVert++] = vQuad[dwTemp+2];
|
|
|
|
dwCurQuad++;
|
|
}
|
|
}
|
|
|
|
m_pVB->Unlock();
|
|
|
|
SAFE_DELETE_ARRAY( vQuad );
|
|
}
|