📄 simpleobject8.cpp
字号:
/*********************************************************************NVMH2****
Path: C:\DEV\devrel\NV_SDK_4\DX8\CommonSrc
File: SimpleObject8.cpp
Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.
Comments:
******************************************************************************/
#include <assert.h>
#include "SimpleObject8.h"
#include "NV_Error.h"
#include <d3d8.h>
#include <d3dx8.h>
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define UL_PI 3.1415926535897932384626433832795028841971693993751
#define UL_SQRT_2 1.4142135623730950488016887242096980785696718753769
#define UL_PI2 (UL_PI/2.0)
#define BOUNDCHK(in, cmp, msg, quit) {if(in>=cmp){DoError(msg,quit);}}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
SimpleObject8::SimpleObject8()
{
m_pVertices = NULL;
m_pIndices = NULL;
m_wNumVerts = 0;
m_wNumInd = 0;
m_PrimType = D3DPT_TRIANGLELIST;
m_bIsValid = false;
}
SimpleObject8::~SimpleObject8()
{
UnAllocate();
}
//////////////////////////////////////////////////////////////////////
void SimpleObject8::UnAllocate()
{
if( m_pVertices )
free( m_pVertices );
if( m_pIndices )
free( m_pIndices );
m_pVertices = NULL;
m_pIndices = NULL;
m_wNumVerts = 0;
m_wNumInd = 0;
m_PrimType = D3DPT_TRIANGLELIST;
m_bIsValid = false;
}
void SimpleObject8::Allocate( WORD nvert, WORD nind )
{
UnAllocate();
m_pVertices = (SimpleObjVertex*) calloc( nvert, sizeof( SimpleObjVertex ) );
NULLCHECK( m_pVertices, "SimpleObject8:: Can't allocate vertices!", true );
m_wNumVerts = nvert;
m_pIndices = (WORD*) calloc( nind, sizeof( WORD ) );
NULLCHECK( m_pIndices, "SimpleObject8:: Can't allocate indices!", true );
m_wNumInd = nind;
}
//-----------------------------------------------------------------------------
// Name: SimpleObject8::InitSphere( float radius, int nLat, int nLong )
// Desc: Make a 'dumb' sphere by sweeping an arc. 'dumb' cause it will have
// a lot of points at the poles
//-----------------------------------------------------------------------------
void SimpleObject8::InitSphere( float radius, int nLat, int nLong )
{
int i,j;
if( nLong < 1 ) nLong = 1;
if( nLat < 3 ) nLat = 3;
if( radius < 0 ) radius = -radius;
nLong++; // repeat edge for texture coord happy
nLat+=2; // two rings on the ends
WORD nvert = nLong * nLat;
WORD ntri = 2 * nLong * nLat;
m_PrimType = D3DPT_TRIANGLELIST;
// Allocate memory:
Allocate( nvert, ntri * 3 );
//m_csDesc = "I'm a sphere!";
//m_csName = "Sphere01";
// make vertex positions
int index;
float ringz; // z cord of a latitude ring
float ring_r; // radius of x,y ring
float theta, rho; // theta = x,y plane angle, rho = z
float x,y,u,v; // x,y coord of pt.
float mag;
for( j=0; j < nLat; j++ )
{
rho = (float)( UL_PI * j / (float)(nLat-1) - UL_PI/2.0f );
ringz = (float) ( radius * sin(rho) );
ring_r = (float) sqrt( radius * radius - ringz*ringz );
for( i=0; i < nLong; i++)
{
theta = (float)( 2* UL_PI * i / (float)( nLong - 1 ) );
x = (float) ( ring_r * cos(theta) );
y = (float) ( ring_r * sin(theta) );
index = i + j*nLong;
if( index > m_wNumVerts )
{
FDebug("InitSphere Error! %n index of only %n allocated!\n", index, m_wNumVerts );
index = m_wNumVerts -1;
}
m_pVertices[ index ].pos.x = x;
m_pVertices[ index ].pos.y = y;
m_pVertices[ index ].pos.z = ringz;
u = (float)( (float)i/(float)(nLong-1) );
v = (float)( (float)j/(float)(nLat-1) );
// Correct for sphere pinch & "degenerate" triangle at caps
if( j==0 )
{
// If at top/bottom of sphere
u -= 0.5f / (float)nLong;
}
else if( j == nLat-1 )
{
// If at top/bottom of sphere
u += 0.5f / (float)nLong;
}
m_pVertices[ index ].t0.x = u;
m_pVertices[ index ].t0.y = v;
//FDebug("U: %f V: %f ind: %d\n", u, v, index );
mag = (float)sqrt( x*x + y*y + ringz*ringz );
m_pVertices[ index ].nrm.x = x/mag;
m_pVertices[ index ].nrm.y = y/mag;
m_pVertices[ index ].nrm.z = ringz/mag;
// m_pVertices[ index ].diffuse = D3DRGB( u, v, 1-u );
m_pVertices[ index ].diffuse = D3DCOLOR_ARGB( 255, 255, 255, 255 );
}
}
// stitch the tris
// Culling is CCW
WORD nind = 0;
WORD i0, i1, i2, i3;
for( j=0; j < nLat-1; j++ )
{
for( i=0; i < nLong; i++)
{
i0 = i + j*nLong;
i1 = i + (j+1)*nLong;
i2 = (i+1)%nLong + j*nLong; // % to wrap back to zero
i3 = (i+1)%nLong + (j+1)*nLong;
BOUNDCHK( nind, m_wNumInd-2, "InitSphere:: Index too high!", true );
m_pIndices[nind++] = i2;
m_pIndices[nind++] = i1;
m_pIndices[nind++] = i0;
BOUNDCHK( nind, m_wNumInd-2, "InitSphere:: Index too high 2!", true );
m_pIndices[nind++] = i3;
m_pIndices[nind++] = i1;
m_pIndices[nind++] = i2;
}
}
m_bIsValid = true;
// all done!
}
void SimpleObject8::InitSpiral( const D3DXVECTOR3 & width_direction,
const D3DXVECTOR3 & height_direction,
float width, float height, int n_sub_width,
int n_sub_height, float n_twists )
{
int i,j;
int nvert, nind;
if( n_sub_height < 0 )
n_sub_height = 0;
if( n_sub_width < 0 )
n_sub_width = 0;
D3DXVECTOR3 width_dir;
D3DXVec3Normalize( &width_dir, &width_direction );
D3DXVECTOR3 height_dir;
D3DXVec3Normalize( &height_dir, &height_direction );
D3DXVECTOR3 length_dir;
D3DXVec3Cross( &length_dir, &width_dir, &height_dir );
nvert = (2 + n_sub_width)*(n_sub_height + 2);
nind = (n_sub_width+1)*(n_sub_height+1)*2 * 3;
Allocate( nvert, nind );
m_PrimType = D3DPT_TRIANGLELIST;
float z;
float dz, dx;
float angle;
float da;
float radius;
z = -height / 2.0f;
angle = 0;
dz = height / (n_sub_height+1.0f);
da = (float)( n_twists * UL_PI * 2.0f ) / (n_sub_height + 1.0f);
dx = width / ( (float)n_sub_width + 1.0f );
int ind;
float wt, ht, lt; // params for each position axis
for( j=0; j < n_sub_height + 2; j++ )
{
for(i=0; i < n_sub_width + 2; i++)
{
radius = width/2.0f - dx * i;
ind = i + j * (n_sub_width+2);
assert( ind < nvert );
wt = radius * (float) sin( angle ); // amount of position in width_dir direction
lt = radius * (float) cos( angle ); // amount of position in height_dir direction
ht = z;
m_pVertices[ ind ].pos.x = wt * width_dir.x + ht * height_dir.x + lt * length_dir.x;
//@ radius * (float) sin( angle );
m_pVertices[ ind ].pos.y = wt * width_dir.y + ht * height_dir.y + lt * length_dir.y;
m_pVertices[ ind ].pos.z = wt * width_dir.z + ht * height_dir.z + lt * length_dir.z;
m_pVertices[ ind ].t0.x = (float)i/(n_sub_width +1.0f);
m_pVertices[ ind ].t0.y = (float)j/(n_sub_height +1.0f);
}
z += dz;
angle += da;
}
// Set the indices
int triind; // triind = index of triangle -> 3 for each
// so 0,1,2 = 1st tri, 3,4,5 = 2nd tri
triind = 0;
for( j=0; j < n_sub_height + 1; j++ )
{
for( i=0; i < n_sub_width + 1; i++ )
{
if( i + j*(n_sub_width + 1) >= nvert )
assert( false );
if( i + 1 + j * ( n_sub_width + 2 ) >= nvert )
assert( false );
if( triind >= nind )
{
FDebug( "bad index calc: %d of %d", triind, nind );
assert( false );
}
// stitching pattern is:
// u,v = 1,1
// v2 -- v1 v2
// | / / |
// |/ / |
// v0 v0 -- v1
// u,v = 0,0
assert( triind < nind );
m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + (j+1)*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);
}
}
}
//@@@@@ fix to call other initspiral
void SimpleObject8::InitSpiral( float width, float height, int n_sub_width,
int n_sub_height, float n_twists )
{
int i,j;
int nvert, nind;
if( n_sub_height < 0 )
n_sub_height = 0;
if( n_sub_width < 0 )
n_sub_width = 0;
nvert = (2 + n_sub_width)*(n_sub_height + 2);
nind = (n_sub_width+1)*(n_sub_height+1)*2 * 3;
Allocate( nvert, nind );
m_PrimType = D3DPT_TRIANGLELIST;
float z;
float dz, dx;
float angle;
float da;
float radius;
z = -height / 2.0f;
angle = 0;
dz = height / (n_sub_height+1.0f);
da = (float)( n_twists * UL_PI * 2.0f ) / (n_sub_height + 1.0f);
dx = width / ( (float)n_sub_width + 1.0f );
int ind;
for( j=0; j < n_sub_height + 2; j++ )
{
for(i=0; i < n_sub_width + 2; i++)
{
radius = width/2.0f - dx * i;
ind = i + j * (n_sub_width+2);
assert( ind < nvert );
m_pVertices[ ind ].pos.x = radius * (float) sin( angle );
m_pVertices[ ind ].pos.y = radius * (float) cos( angle );
m_pVertices[ ind ].pos.z = z;
m_pVertices[ ind ].t0.x = (float)i/(n_sub_width +1.0f);
m_pVertices[ ind ].t0.y = (float)j/(n_sub_height +1.0f);
}
z += dz;
angle += da;
}
// Set the indices
int triind; // triind = index of triangle -> 3 for each
// so 0,1,2 = 1st tri, 3,4,5 = 2nd tri
triind = 0;
for( j=0; j < n_sub_height + 1; j++ )
{
for( i=0; i < n_sub_width + 1; i++ )
{
if( i + j*(n_sub_width + 1) >= nvert )
assert( false );
if( i + 1 + j * ( n_sub_width + 2 ) >= nvert )
assert( false );
if( triind >= nind )
{
FDebug( "bad index calc: %d of %d", triind, nind );
assert( false );
}
// stitching pattern is:
// x,z = 1,1
// v2 -- v1 v2
// | / / |
// |/ / |
// v0 v0 -- v1
// x,z = 0,0
assert( triind < nind );
m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + j*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + (j+1)*(n_sub_width+2);
assert( triind < nind );
m_pIndices[ triind++ ] = i + 1 + (j+1)*(n_sub_width+2);
}
}
}
void SimpleObject8::InitTorusWrapped( float InnerRadius, float OuterRadius, UINT Sides, UINT Rings )
{
// Creates a torus "spun" about the z axis.
// This one has no overlapping vertices on the seams,
// so you must use texture coordinate wrapping when
// drawing it.
UINT i,j;
int nvert, nind;
if( Sides < 3 )
Sides = 3;
if( Rings < 3 )
Rings = 3;
if( InnerRadius > OuterRadius )
{
float tmp = InnerRadius;
InnerRadius = OuterRadius;
OuterRadius = InnerRadius;
}
nvert = Sides * Rings;
nind = 3 * Sides * 2 * Rings; // # of triangle vertex indices
// allocate memory for vertices
Allocate( nvert, nind );
m_PrimType = D3DPT_TRIANGLELIST; // Could optimize to create tri
// strips, but not today!
// Fill in vertex data
// phi is angle around z axis
// theta is angle around each ring
float d_phi = 2.0f * (float)UL_PI / ((float)Rings);
float d_theta = 2.0f * (float)UL_PI / ((float)Sides);
float cent_radius = (InnerRadius + OuterRadius) / 2.0f;
float ring_radius = (OuterRadius - InnerRadius) / 2.0f;
float angle;
SimpleObjVertex * pRing = (SimpleObjVertex*) calloc( Sides, sizeof( SimpleObjVertex));
NULLCHECK( pRing, "SimpleObject8:: Can't allocate a ring of vertices!", true );
// make the first ring - centered about cent_radius;
for( i=0; i < Sides; i++ )
{
angle = 2.0f * (float)UL_PI * (float)i / (float)Sides;
pRing[i].pos.x = ring_radius * ((float)cos( angle ));
pRing[i].pos.z = ring_radius * ((float)sin( angle ));
pRing[i].pos.y = 0.0f;
pRing[i].pos.x += cent_radius;
// Set normals
pRing[i].nrm.x = (float) cos( angle );
pRing[i].nrm.z = (float) sin( angle );
pRing[i].nrm.y = 0.0f;
pRing[i].t0.x = (float)i / (float)Sides;
}
int vind;
float nx, ny, nz, length;
vind = 0;
for( j=0; j < Rings; j++ )
{
// rotate each ring into position
// around the sweep angle
angle = 2.0f * (float)UL_PI * (float)j / (float) Rings;
for( i=0; i < Sides; i++, vind++ )
{
assert( vind < nvert );
m_pVertices[ vind ].pos.x = pRing[i].pos.x * ((float)cos( angle ));
m_pVertices[ vind ].pos.y = pRing[i].pos.x * ((float)sin( angle ));
m_pVertices[ vind ].pos.z = pRing[i].pos.z;
// rotate normals into position
nx = m_pVertices[ vind ].nrm.x = pRing[i].nrm.x * ((float)cos(angle));
ny = m_pVertices[ vind ].nrm.y = pRing[i].nrm.x * ((float)sin(angle));
nz = m_pVertices[ vind ].nrm.z = pRing[i].nrm.z;
// normalize normals. Shouldn't have to in this case, but
// just a safety measure.
length = (float) sqrt(nx*nx + ny*ny + nz*nz);
assert( length > 0.0f );
m_pVertices[ vind ].nrm.x = nx / length;
m_pVertices[ vind ].nrm.y = ny / length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -