mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
1191 lines
40 KiB
C++
1191 lines
40 KiB
C++
#include "nx_init.h"
|
|
#include "instance.h"
|
|
#include "anim.h"
|
|
#include "render.h"
|
|
#include "gfx\camera.h"
|
|
#include "gfx\nx.h"
|
|
#include "occlude.h"
|
|
#include "charpipeline\skinning.h"
|
|
#include "sys/ngc/p_gx.h"
|
|
#include "sys/ngc/p_aram.h"
|
|
#include "sys/ngc/p_dma.h"
|
|
#include <gfx\NxLight.h>
|
|
#include "sys/ngc/p_buffer.h"
|
|
#include <sys/profiler.h>
|
|
#include "sys/ngc/p_display.h"
|
|
|
|
#include "dolphin/base/ppcwgpipe.h"
|
|
#include "dolphin/gx/gxvert.h"
|
|
|
|
bool g_in_cutscene = false;
|
|
|
|
int g_twiddle = 900;
|
|
|
|
int g_hash_items = 0;
|
|
|
|
int g_count = 0;
|
|
|
|
float g_tweak = 0.0f;
|
|
|
|
float NEAR_Z = 50.0f;
|
|
float FAR_Z = 150.0f;
|
|
|
|
float MIN_LEN = 10.0f;
|
|
float MAX_LEN = 80.0f;
|
|
|
|
extern int gNewRender;
|
|
extern int g_object;
|
|
|
|
extern bool g_mc_hack;
|
|
|
|
//#define DEBUG_SPHERES
|
|
|
|
extern "C" {
|
|
|
|
extern void TransformSingle ( ROMtx m, s16 * srcBase, s16 * dstBase, u32 count );
|
|
extern void TransformDouble ( ROMtx m0, ROMtx m1, s16 * wtBase, s16 * srcBase, s16 * dstBase, u32 count );
|
|
extern void TransformAcc ( ROMtx m, u16 count, s16 * srcBase, s16 * dstBase, u16 * indices, s16 * weights );
|
|
extern void ConvertFixed196ToFloat ( s16 * p_source, float * p_dest, int count );
|
|
extern void CalculateDotProducts ( s16 * p_xyz, u16 * p_index_list, float * p_dot, int count, float px, float py, float pz );
|
|
extern void RenderShadows ( s16 * p_xyz, u16 * p_index_list, NxNgc::sShadowEdge * p_neighbor_list, float * p_dot, int count, float px, float py, float pz, float tx, float ty, float tz );
|
|
|
|
}
|
|
|
|
//static char doubleBuffer0[(100*1024)+32];
|
|
//static char doubleBuffer1[(100*1024)+32];
|
|
//static uint32 *p_double[2] = { (uint32 *)OSRoundUp32B(doubleBuffer0), (uint32 *)OSRoundUp32B(doubleBuffer1) };
|
|
//
|
|
//static volatile bool dmaComplete;
|
|
//
|
|
//static void arqCallback( u32 pointerToARQRequest )
|
|
//{
|
|
// dmaComplete = true;
|
|
//}
|
|
|
|
namespace NxNgc
|
|
{
|
|
|
|
|
|
//Lst::HashTable< CInstance > *pInstanceTable = NULL;
|
|
|
|
static Mth::Matrix *pLastBoneTransforms = NULL;
|
|
CInstance *pFirstInstance = NULL;
|
|
#if 0
|
|
static CInstance *pAnimInstance[256];
|
|
static int instanceCount = 0;
|
|
#endif
|
|
|
|
#define INSTANCE_ARRAY_SIZE 2048
|
|
static CInstance *p_instances[INSTANCE_ARRAY_SIZE];
|
|
int current_index = 0;
|
|
|
|
void InitialiseInstanceTable( void )
|
|
{
|
|
// if( pInstanceTable == NULL )
|
|
// {
|
|
// pInstanceTable = new Lst::HashTable<CInstance>( 8 );
|
|
// }
|
|
}
|
|
|
|
|
|
//bool frustum_check_sphere( NsVector * p_center, float radius )
|
|
//{
|
|
// bool visible = true;
|
|
//
|
|
// NsVector out;
|
|
//
|
|
// EngineGlobals.local_to_camera.multiply( p_center, &out );
|
|
//
|
|
// float x = out.x;
|
|
// float y = out.y;
|
|
// float z = out.z;
|
|
// float R = radius;
|
|
//
|
|
// if (R<z-EngineGlobals.near || R<EngineGlobals.far-z || R<EngineGlobals.sy*z+EngineGlobals.cy*y || R<EngineGlobals.sy*z-EngineGlobals.cy*y || R<EngineGlobals.sx*z-EngineGlobals.cx*x || R<EngineGlobals.sx*z+EngineGlobals.cx*x) visible = false;
|
|
//
|
|
// return visible;
|
|
//}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
#ifdef DEBUG_SPHERES
|
|
static void debug_render_sphere( Mth::Vector sphere, GXColor color )
|
|
{
|
|
GX::SetPointSize( 6, GX_TO_ONE );
|
|
|
|
GX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );
|
|
GX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_FALSE, GX_PTIDENTITY );
|
|
GX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );
|
|
GX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);
|
|
|
|
GX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA,
|
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV,
|
|
GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
|
|
|
GX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,
|
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
|
GX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
|
GX::SetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
|
GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255} );
|
|
GX::SetChanMatColor( GX_COLOR0A0, color );
|
|
|
|
GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );
|
|
|
|
GX::Begin( GX_LINES, GX_VTXFMT0, 6 );
|
|
GX::Position3f32( sphere[X] - sphere[W] , sphere[Y] , sphere[Z] );
|
|
GX::Position3f32( sphere[X] + sphere[W] , sphere[Y] , sphere[Z] );
|
|
GX::Position3f32( sphere[X] , sphere[Y] - sphere[W] , sphere[Z] );
|
|
GX::Position3f32( sphere[X] , sphere[Y] + sphere[W] , sphere[Z] );
|
|
GX::Position3f32( sphere[X] , sphere[Y] , sphere[Z] - sphere[W] );
|
|
GX::Position3f32( sphere[X] , sphere[Y] , sphere[Z] + sphere[W] );
|
|
GX::End();
|
|
|
|
#define NUM_SEGMENTS 32
|
|
#define SEGMENT_STEP ( 1.0f / (float)NUM_SEGMENTS )
|
|
|
|
GX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 );
|
|
for ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )
|
|
{
|
|
GX::Position3f32( sphere[X] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),
|
|
sphere[Y] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),
|
|
sphere[Z] );
|
|
}
|
|
GX::End();
|
|
|
|
GX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 );
|
|
for ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )
|
|
{
|
|
GX::Position3f32( sphere[X] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),
|
|
sphere[Y],
|
|
sphere[Z] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ) );
|
|
}
|
|
GX::End();
|
|
|
|
GX::Begin( GX_LINESTRIP, GX_VTXFMT0, NUM_SEGMENTS + 1 );
|
|
for ( int lp = 0; lp < (NUM_SEGMENTS+1); lp++ )
|
|
{
|
|
GX::Position3f32( sphere[X],
|
|
sphere[Y] + ( sinf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ),
|
|
sphere[Z] + ( cosf( Mth::PI * 2.0f * ( SEGMENT_STEP * (float)lp ) ) * sphere[W] ) );
|
|
}
|
|
GX::End();
|
|
}
|
|
#endif DEBUG_SPHERES
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
static int sort_by_bone_transform( const void *p1, const void *p2 )
|
|
{
|
|
CInstance *p_mesh1 = *((CInstance**)p1 );
|
|
CInstance *p_mesh2 = *((CInstance**)p2 );
|
|
|
|
// Mth::Matrix *p_mat1 = p_mesh1->GetBoneTransforms();
|
|
// Mth::Matrix *p_mat2 = p_mesh2->GetBoneTransforms();
|
|
|
|
// Setup some required pointers for both transforms.
|
|
uint32 p_mat1 = (uint32)p_mesh1->GetScene()->mp_dl->mp_object_header->m_num_skin_verts;
|
|
uint32 p_mat2 = (uint32)p_mesh2->GetScene()->mp_dl->mp_object_header->m_num_skin_verts;
|
|
|
|
if(( p_mat1 == 0 ) || ( p_mesh1->GetScene()->m_numHierarchyObjects > 0 ))
|
|
{
|
|
if(( p_mat2 == NULL ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))
|
|
{
|
|
int num_st1 = p_mesh1->GetScene()->m_num_filled_meshes - p_mesh1->GetScene()->m_num_opaque_meshes;
|
|
int num_st2 = p_mesh2->GetScene()->m_num_filled_meshes - p_mesh2->GetScene()->m_num_opaque_meshes;
|
|
|
|
if( num_st1 == num_st2 )
|
|
{
|
|
// Try sorting on the material draw order of the first semitransparent mesh.
|
|
if( num_st1 > 0 )
|
|
{
|
|
NxNgc::sMaterialHeader *p_material1 = p_mesh1->GetScene()->mpp_mesh_list[p_mesh1->GetScene()->m_num_opaque_meshes]->mp_dl->m_material.p_header;
|
|
NxNgc::sMaterialHeader *p_material2 = p_mesh2->GetScene()->mpp_mesh_list[p_mesh2->GetScene()->m_num_opaque_meshes]->mp_dl->m_material.p_header;
|
|
|
|
if( p_material1 && p_material2 )
|
|
{
|
|
return ( p_material1->m_draw_order > p_material2->m_draw_order ) ? 1 : (( p_material1->m_draw_order < p_material2->m_draw_order ) ? -1 : 0 );
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return ( num_st1 > num_st2 ) ? 1 : -1;
|
|
}
|
|
return 1;
|
|
}
|
|
else if(( p_mat2 == 0 ) || ( p_mesh2->GetScene()->m_numHierarchyObjects > 0 ))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// At this stage we know both instances have bone transforms.
|
|
if( p_mat1 == p_mat2 )
|
|
{
|
|
int num_st1 = p_mesh1->GetScene()->m_num_filled_meshes - p_mesh1->GetScene()->m_num_opaque_meshes;
|
|
int num_st2 = p_mesh2->GetScene()->m_num_filled_meshes - p_mesh2->GetScene()->m_num_opaque_meshes;
|
|
|
|
if( num_st1 == num_st2 )
|
|
return 0;
|
|
|
|
return ( num_st1 > num_st2 ) ? 1 : -1;
|
|
}
|
|
|
|
return((uint32)p_mat1 > (uint32)p_mat2 ) ? 1 : -1;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
void render_instance( CInstance *p_instance, uint32 flags )
|
|
{
|
|
// // Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.
|
|
// pLastBoneTransforms = NULL;
|
|
//
|
|
// if( p_instance->GetActive())
|
|
// {
|
|
// // Check whether this instance is visible.
|
|
// set_frustum_bbox_transform( p_instance->GetTransform());
|
|
// float sphere[4];
|
|
// sphere[0] = p_instance->GetScene()->m_sphere_center.x;
|
|
// sphere[1] = p_instance->GetScene()->m_sphere_center.y;
|
|
// sphere[2] = p_instance->GetScene()->m_sphere_center.z;
|
|
// sphere[3] = p_instance->GetScene()->m_sphere_radius;
|
|
// if( frustum_check_sphere( sphere ))
|
|
// {
|
|
// if( !TestSphereAgainstOccluders( (Mth::Vector*)&p_instance->GetScene()->m_sphere_center, p_instance->GetScene()->m_sphere_radius ))
|
|
// {
|
|
// p_instance->Render( flags | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT );
|
|
//
|
|
//// // Restore world transform to identity.
|
|
//// D3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );
|
|
//// set_frustum_bbox_transform( NULL );
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
void render_instances( uint32 flags )
|
|
{
|
|
int save_g_object = g_object;
|
|
|
|
if( current_index > 0 )
|
|
{
|
|
int i = 0;
|
|
|
|
// Mth::Matrix *pLast = NULL;
|
|
// ROMtx bone_mtx[80];
|
|
|
|
for( ; i < current_index; ++i )
|
|
{
|
|
#ifndef __NOPT_FINAL__
|
|
g_object = p_instances[i]->m_object_num;
|
|
#endif // __NOPT_FINAL__
|
|
// if ( ( flags & NxNgc::vRENDER_TRANSFORM ) && ( p_instances[i]->GetFlags() & NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME ) )
|
|
// {
|
|
//// p_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, bone_mtx, pLast );
|
|
//// pLast = p_instances[i]->GetBoneTransforms();
|
|
// p_instances[i]->ClearFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );
|
|
// }
|
|
|
|
if(( p_instances[i]->GetBoneTransforms() == NULL ) || ( p_instances[i]->GetScene()->m_numHierarchyObjects > 0 ))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_PRE_WORLD_SEMITRANSPARENT )))
|
|
{
|
|
p_instances[i]->Render( flags );
|
|
// p_instances[i]->SetFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );
|
|
}
|
|
}
|
|
|
|
for( ; i < current_index; ++i )
|
|
{
|
|
#ifndef __NOPT_FINAL__
|
|
g_object = p_instances[i]->m_object_num;
|
|
#endif // __NOPT_FINAL__
|
|
|
|
// if(( p_instances[i]->GetBoneTransforms()) && ( p_instances[i]->GetScene()->m_numHierarchyObjects == 0 ))
|
|
// break;
|
|
|
|
if(( flags & vRENDER_OPAQUE ) || (( flags & vRENDER_SEMITRANSPARENT ) && ( flags & vRENDER_INSTANCE_POST_WORLD_SEMITRANSPARENT )))
|
|
{
|
|
p_instances[i]->Render( flags );
|
|
}
|
|
}
|
|
}
|
|
g_object = save_g_object;
|
|
}
|
|
|
|
void CInstance::Transform( uint32 flags, ROMtx * p_mtx_buffer, Mth::Matrix *p_mtx_last )
|
|
{
|
|
//# ifdef __USE_PROFILER__
|
|
//// Sys::VUProfiler->PushContext( 128,0,0 );
|
|
//# endif // __USE_PROFILER__
|
|
|
|
// if ( gNewRender ) render_flags |= NxNgc::vRENDER_NEW_TEST;
|
|
|
|
if( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )
|
|
{
|
|
// Has bone transforms, is therefore an animated object such as a skater, pedestrian etc.
|
|
mp_posNormRenderBuffer = GetPosNormalBuffer( 0 );
|
|
|
|
if ( !p_mtx_last || ( GetBoneTransforms() != p_mtx_last ) )
|
|
{
|
|
float * ps;
|
|
float * pd;
|
|
for( int i = 0; i < GetNumBones(); ++i )
|
|
{
|
|
ps = (float*)&GetBoneTransforms()[i];
|
|
pd = (float*)&p_mtx_buffer[i][0][0];
|
|
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
*pd++ = *ps++;
|
|
}
|
|
}
|
|
|
|
// Setup some required pointers for both transforms.
|
|
// sMesh* p_mesh = GetScene()->mpp_mesh_list[0];
|
|
// if ( GetScene()->m_num_opaque_entries )
|
|
// {
|
|
// p_mesh = GetScene()->m_opaque_meshes[0];
|
|
// }
|
|
// else if ( GetScene()->m_num_semitransparent_entries )
|
|
// {
|
|
// p_mesh = GetScene()->m_semitransparent_meshes[0];
|
|
// }
|
|
// else
|
|
// {
|
|
// Dbg_MsgAssert(0, ("No meshes in scene."));
|
|
// p_mesh = NULL;
|
|
// }
|
|
|
|
// Transform the single lists.
|
|
uint32* p32 = (uint32 *)GetScene()->mp_dl->mp_object_header->m_skin.p_data;
|
|
s16* p_pos = mp_posNormRenderBuffer;
|
|
for ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_single_lists; lp++ ) {
|
|
uint32 pairs = *p32++;
|
|
uint32 mtx = *p32++;
|
|
s16* p_pn = (s16 *)p32;
|
|
ROMtxPtr p_bone = p_mtx_buffer[mtx];
|
|
|
|
TransformSingle( p_bone, p_pn, p_pos, pairs == 1 ? 2 : pairs );
|
|
p_pos += (6 * pairs);
|
|
p32 = (uint32 *)&p_pn[pairs*6];
|
|
}
|
|
|
|
// Transform the double lists.
|
|
for ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_double_lists; lp++ ) {
|
|
uint32 pairs = *p32++;
|
|
uint32 mtx = *p32++;
|
|
s16* p_pn = (s16 *)p32;
|
|
ROMtxPtr p_bone0 = p_mtx_buffer[mtx&255];
|
|
ROMtxPtr p_bone1 = p_mtx_buffer[(mtx>>8)&255];
|
|
s16* p_weight = (s16 *)&p_pn[(6*pairs)];
|
|
|
|
TransformDouble( p_bone0, p_bone1, p_weight, p_pn, p_pos, pairs == 1 ? 2 : pairs );
|
|
p_pos += (6 * pairs);
|
|
p32 = (uint32 *)&p_weight[pairs*2];
|
|
}
|
|
|
|
// Transform the acc lists.
|
|
for ( uint32 lp = 0; lp < GetScene()->mp_dl->mp_object_header->m_num_add_lists; lp++ ) {
|
|
uint32 singles = *p32++;
|
|
uint32 mtx = *p32++;
|
|
s16* p_pn = (s16 *)p32;
|
|
ROMtxPtr p_bone = p_mtx_buffer[mtx];
|
|
s16* p_weight = (s16 *)&p_pn[(6*singles)];
|
|
uint16* p_index = (uint16 *)&p_weight[singles];
|
|
|
|
TransformAcc( p_bone, singles, p_pn, mp_posNormRenderBuffer, p_index, p_weight );
|
|
// p32 = (uint32 *)&p_index[singles+(singles&1)];
|
|
p32 = (uint32 *)&p_index[singles];
|
|
}
|
|
|
|
|
|
|
|
// int num_vertex;
|
|
// if ( mp_scene->m_num_opaque_entries )
|
|
// {
|
|
// num_vertex = mp_scene->m_opaque_meshes[0]->m_num_vertex;
|
|
// }
|
|
// else if ( mp_scene->m_num_semitransparent_entries )
|
|
// {
|
|
// num_vertex = mp_scene->m_semitransparent_meshes[0]->m_num_vertex;
|
|
// }
|
|
// else
|
|
// {
|
|
// Dbg_MsgAssert(0, ("No meshes in scene."));
|
|
// num_vertex = 0;
|
|
// }
|
|
//
|
|
int num_vertex = GetScene()->mp_dl->mp_object_header->m_num_skin_verts;
|
|
DCFlushRange ( mp_posNormRenderBuffer, sizeof ( s16 ) * 6 * ( num_vertex + 1 ) );
|
|
}
|
|
//# ifdef __USE_PROFILER__
|
|
//// Sys::VUProfiler->PopContext( );
|
|
//# endif // __USE_PROFILER__
|
|
}
|
|
|
|
|
|
|
|
void CInstance::Render( uint32 flags )
|
|
{
|
|
uint32 render_flags = flags;
|
|
// if ( gNewRender ) render_flags |= NxNgc::vRENDER_NEW_TEST;
|
|
|
|
NsMatrix root;
|
|
|
|
root.setRightX( GetTransform()->GetRight()[X] );
|
|
root.setRightY( GetTransform()->GetUp()[X] );
|
|
root.setRightZ( GetTransform()->GetAt()[X] );
|
|
|
|
root.setUpX( GetTransform()->GetRight()[Y] );
|
|
root.setUpY( GetTransform()->GetUp()[Y] );
|
|
root.setUpZ( GetTransform()->GetAt()[Y] );
|
|
|
|
root.setAtX( GetTransform()->GetRight()[Z] );
|
|
root.setAtY( GetTransform()->GetUp()[Z] );
|
|
root.setAtZ( GetTransform()->GetAt()[Z] );
|
|
|
|
root.setPosX( GetTransform()->GetPos()[X] );
|
|
root.setPosY( GetTransform()->GetPos()[Y] );
|
|
root.setPosZ( GetTransform()->GetPos()[Z] );
|
|
|
|
// Mth::Vector world_sphere(GetScene()->m_sphere_center.x,GetScene()->m_sphere_center.y,GetScene()->m_sphere_center.z);
|
|
// world_sphere[W] = 1.0f;
|
|
// world_sphere *= *GetTransform(); // => use mp_transform
|
|
// if (TestSphereAgainstOccluders( &world_sphere, GetScene()->m_sphere_radius ))
|
|
// {
|
|
// return;
|
|
// }
|
|
|
|
// Create & upload current view matrix.
|
|
NsMatrix tr;
|
|
tr.cat( EngineGlobals.world_to_camera, root );
|
|
GX::LoadPosMtxImm( (MtxPtr)&tr, GX_PNMTX0 );
|
|
|
|
// Need to force the current matrix to be just incase hierarchical models change it to 1.
|
|
if ( render_flags & vRENDER_SHADOW_1ST_PASS )
|
|
{
|
|
GX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );
|
|
}
|
|
|
|
// if ( !( render_flags & vRENDER_SHADOW_1ST_PASS ) )
|
|
{
|
|
//NsMatrix inv;
|
|
//inv.invert( root );
|
|
//GX::LoadNrmMtxImm((MtxPtr)&inv, GX_PNMTX0);
|
|
// tr.cat( EngineGlobals.camera, root );
|
|
// tr.invert( root/*EngineGlobals.world_to_camera*/ );
|
|
|
|
Nx::CModelLights *p_lights = GetModel() ? GetModel()->GetModelLights() : NULL;
|
|
if( p_lights )
|
|
{
|
|
p_lights->UpdateEngine( GetTransform()->GetPos(), true );
|
|
}
|
|
else
|
|
{
|
|
Nx::CLightManager::sUpdateEngine();
|
|
}
|
|
}
|
|
MTXCopy ( (MtxPtr)&tr, EngineGlobals.current_uploaded );
|
|
|
|
EngineGlobals.local_to_camera.copy( tr );
|
|
|
|
EngineGlobals.object_pos.x = tr.getPosX();
|
|
EngineGlobals.object_pos.y = tr.getPosY();
|
|
EngineGlobals.object_pos.z = tr.getPosZ();
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_SPHERES
|
|
if( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )
|
|
{
|
|
Mth::Vector sphere = GetScene()->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;
|
|
debug_render_sphere( sphere, (GXColor){255,0,0,255} );
|
|
}
|
|
else
|
|
{
|
|
if ( GetScene()->m_numHierarchyObjects && GetBoneTransforms() )
|
|
{
|
|
// Car or something...
|
|
Mth::Vector sphere = GetScene()->m_sphere; //mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;
|
|
debug_render_sphere( sphere, (GXColor){0,255,0,255} );
|
|
}
|
|
else
|
|
{
|
|
// No bones, just render normally. Must be a trashcan or something.
|
|
Mth::Vector sphere = GetScene()->mpp_mesh_list[0]->mp_dl->mp_object_header->m_sphere;
|
|
debug_render_sphere( sphere, (GXColor){0,0,255,255} );
|
|
}
|
|
}
|
|
#endif // DEBUG_SPHERES
|
|
|
|
|
|
|
|
|
|
|
|
GXLightObj light_obj[3];
|
|
|
|
// Always set ambient & diffuse colors.
|
|
GX::SetChanAmbColor( GX_COLOR0A0, NxNgc::EngineGlobals.ambient_light_color );
|
|
// GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){128,128,128,255} );
|
|
// GX::SetChanAmbColor( GX_COLOR1A1, NxNgc::EngineGlobals.ambient_light_color );
|
|
|
|
GX::InitLightColor( &light_obj[0], NxNgc::EngineGlobals.diffuse_light_color[0] );
|
|
GX::InitLightPos( &light_obj[0], NxNgc::EngineGlobals.light_x[0], NxNgc::EngineGlobals.light_y[0], NxNgc::EngineGlobals.light_z[0] );
|
|
GX::LoadLightObjImm( &light_obj[0], GX_LIGHT0 );
|
|
|
|
GX::InitLightColor( &light_obj[1], NxNgc::EngineGlobals.diffuse_light_color[1] );
|
|
GX::InitLightPos( &light_obj[1], NxNgc::EngineGlobals.light_x[1], NxNgc::EngineGlobals.light_y[1], NxNgc::EngineGlobals.light_z[1] );
|
|
GX::LoadLightObjImm( &light_obj[1], GX_LIGHT1 );
|
|
|
|
GX::InitLightColor( &light_obj[2], NxNgc::EngineGlobals.diffuse_light_color[2] );
|
|
GX::InitLightPos( &light_obj[2], NxNgc::EngineGlobals.light_x[2], NxNgc::EngineGlobals.light_y[2], NxNgc::EngineGlobals.light_z[2] );
|
|
GX::LoadLightObjImm( &light_obj[2], GX_LIGHT2 );
|
|
|
|
// Set channel control for diffuse.
|
|
GX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT0|GX_LIGHT1|GX_LIGHT2, GX_DF_CLAMP, GX_AF_NONE );
|
|
GX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( GetBoneTransforms() && ( GetScene()->m_numHierarchyObjects == 0 ) )
|
|
{
|
|
// Has bone transforms, is therefore an animated object such as a skater, pedestrian etc.
|
|
|
|
// if ( ( flags & vRENDER_SHADOW_1ST_PASS ) && GetScene()->mp_scene_data && GetScene()->mp_scene_data->m_num_shadow_faces && !g_in_cutscene )
|
|
// {
|
|
// f32 p_pm[GX_PROJECTION_SZ];
|
|
// GX::GetProjectionv( p_pm );
|
|
// float value = p_pm[6] + ( (float)(-g_twiddle) ) * p_pm[5];
|
|
//
|
|
// GXWGFifo.u8 = GX_LOAD_XF_REG;
|
|
// GXWGFifo.u16 = 0;
|
|
// GXWGFifo.u16 = 0x1025;
|
|
// GXWGFifo.f32 = value;
|
|
//
|
|
//
|
|
// GX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_FRONT );
|
|
// GX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );
|
|
// GX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );
|
|
//
|
|
// GX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0,
|
|
// GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
|
|
//
|
|
// GX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_KONST, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,
|
|
// GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
|
|
// GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
|
// GX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_KONST, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO,
|
|
// GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
|
//
|
|
// GX::SetVtxDesc( 1, GX_VA_POS, GX_DIRECT );
|
|
//
|
|
// GX::SetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
|
//
|
|
//// GX::SetZMode( GX_TRUE, GX_GREATER, GX_FALSE );
|
|
//// GX::SetZMode( GX_TRUE, GX_GREATER, GX_FALSE );
|
|
// GX::SetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);
|
|
//
|
|
// GX::SetTevKColor( GX_KCOLOR0, (GXColor){4,4,4,4} );
|
|
// GX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );
|
|
//
|
|
//// if ( !g_in_cutscene ) GX::SetClipMode( GX_CLIP_DISABLE );
|
|
// GX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );
|
|
//
|
|
//
|
|
// float px = 0.0f; //NxNgc::EngineGlobals.skater_shadow_dir.x;
|
|
// float py = -1.0f; //NxNgc::EngineGlobals.skater_shadow_dir.y * 3.0f;
|
|
// float pz = 0.0f; //NxNgc::EngineGlobals.skater_shadow_dir.z;
|
|
//
|
|
// float l = sqrtf( ( px * px ) + ( py * py ) + ( pz * pz ) );
|
|
//
|
|
// px /= l;
|
|
// py /= l;
|
|
// pz /= l;
|
|
//
|
|
////#define NEAR_Z 50.0f
|
|
////#define FAR_Z 120.0f
|
|
////
|
|
////#define MIN_LEN 10.0f
|
|
////#define MAX_LEN 100.0f
|
|
//
|
|
// // Shorten length if:
|
|
// // 1. light vector & object vector are opposing.
|
|
// // AND
|
|
// // 2. camera is not above player.
|
|
// // AND
|
|
// // 3. camera is close to the object.
|
|
// float base_length = MAX_LEN;
|
|
//
|
|
//// float cx = NxNgc::EngineGlobals.camera.getPosX() - GetTransform()->GetPos()[X];
|
|
//// float cy = NxNgc::EngineGlobals.camera.getPosY() - GetTransform()->GetPos()[Y];
|
|
//// float cz = NxNgc::EngineGlobals.camera.getPosZ() - GetTransform()->GetPos()[Z];
|
|
//
|
|
//// float obj_len = sqrtf( ( cx * cx ) + /*( cy * cy ) +*/ ( cz * cz ) );
|
|
//
|
|
////
|
|
//// // Fabricate a worst-case vector.
|
|
//// // 1st, pick a point at the head of the skater.
|
|
//// float wx = 0.0f;
|
|
//// float wy = 12.0f * 7.0f; // Assuming 7ft skater.
|
|
//// float wz = 0.0f;
|
|
////
|
|
//// // 2nd, move towards camera by average value.
|
|
//// wx += ( cx / obj_len ) * ( 12.0f * 3.0f );
|
|
//// wy += ( cy / obj_len ) * ( 12.0f * 3.0f );
|
|
//// wz += ( cz / obj_len ) * ( 12.0f * 3.0f );
|
|
////
|
|
//
|
|
//// float cam_dir_dot = ( px * cx ) + /*( py * cy ) +*/ ( pz * cz );
|
|
////
|
|
////// OSReport( "Object len: %8.3f\n", obj_len );
|
|
////
|
|
//// if ( ( ( cam_dir_dot > -0.0f ) || ( obj_len <= NEAR_Z ) ) && ( cy < 100.0f ) )
|
|
//// {
|
|
//// // Opposing, get length.
|
|
//// if ( obj_len < FAR_Z )
|
|
//// {
|
|
//// if ( obj_len > NEAR_Z )
|
|
//// {
|
|
//// // Close enough, adjust base length.
|
|
//// base_length = MIN_LEN + ( ( ( obj_len - NEAR_Z ) * ( MAX_LEN - MIN_LEN ) ) / ( FAR_Z - NEAR_Z ) );
|
|
//// }
|
|
//// else
|
|
//// {
|
|
//// // Close enough, adjust base length.
|
|
//// base_length = MIN_LEN;
|
|
//// }
|
|
//// }
|
|
//// }
|
|
////
|
|
// float length = NxNgc::EngineGlobals.skater_height + base_length;
|
|
//
|
|
// root.setRightX( GetTransform()->GetRight()[X] );
|
|
// root.setRightY( GetTransform()->GetRight()[Y] );
|
|
// root.setRightZ( GetTransform()->GetRight()[Z] );
|
|
//
|
|
// root.setUpX( GetTransform()->GetUp()[X] );
|
|
// root.setUpY( GetTransform()->GetUp()[Y] );
|
|
// root.setUpZ( GetTransform()->GetUp()[Z] );
|
|
//
|
|
// root.setAtX( GetTransform()->GetAt()[X] );
|
|
// root.setAtY( GetTransform()->GetAt()[Y] );
|
|
// root.setAtZ( GetTransform()->GetAt()[Z] );
|
|
//
|
|
// root.setPosX( 0.0f );
|
|
// root.setPosY( 0.0f );
|
|
// root.setPosZ( 0.0f );
|
|
//
|
|
// NsVector in, out;
|
|
//
|
|
// in.x = px;
|
|
// in.y = py;
|
|
// in.z = pz;
|
|
// root.multiply( &in, &out );
|
|
// px = out.x;
|
|
// py = out.y;
|
|
// pz = out.z;
|
|
//
|
|
// float tx = px * g_tweak;
|
|
// float ty = py * g_tweak;
|
|
// float tz = pz * g_tweak;
|
|
//
|
|
// px *= length;
|
|
// py *= length;
|
|
// pz *= length;
|
|
//
|
|
// int num_shadow_faces = GetScene()->mp_scene_data->m_num_shadow_faces;
|
|
//
|
|
// float p_dot[4096];
|
|
// CalculateDotProducts( mp_posNormRenderBuffer, GetScene()->mp_shadow_volume_mesh, p_dot, num_shadow_faces, px, py, pz );
|
|
//#if 1
|
|
// RenderShadows( mp_posNormRenderBuffer, GetScene()->mp_shadow_volume_mesh, GetScene()->mp_shadow_edge, p_dot, num_shadow_faces, px, py, pz, tx, ty, tz );
|
|
//#else
|
|
// float * p_xyz = new float[mp_scene->mp_dl->mp_object_header->m_num_skin_verts*3];
|
|
// ConvertFixed196ToFloat( mp_posNormRenderBuffer, p_xyz, mp_scene->mp_dl->mp_object_header->m_num_skin_verts );
|
|
//
|
|
// for ( uint lp = 0; lp < GetScene()->mp_scene_data->m_num_shadow_faces; lp++ )
|
|
// {
|
|
// float dot = p_dot[lp];
|
|
//
|
|
// if ( dot > 0 )
|
|
// {
|
|
//// // See if we have to draw all sides.
|
|
//// // Check 01.
|
|
// int shape = 0;
|
|
// if ( ( GetScene()->mp_shadow_edge[lp].neighbor[0] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[0] ] <= 0 ) )
|
|
// {
|
|
// shape |= (1<<0);
|
|
// }
|
|
// // Check 12.
|
|
// if ( ( GetScene()->mp_shadow_edge[lp].neighbor[1] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[1] ] <= 0 ) )
|
|
// {
|
|
// shape |= (1<<1);
|
|
// }
|
|
// // Check 23.
|
|
// if ( ( GetScene()->mp_shadow_edge[lp].neighbor[2] == -1 ) || ( p_dot[ GetScene()->mp_shadow_edge[lp].neighbor[2] ] <= 0 ) )
|
|
// {
|
|
// shape |= (1<<2);
|
|
// }
|
|
//
|
|
// unsigned short idx0 = GetScene()->mp_shadow_volume_mesh[(lp*3)+0];
|
|
// unsigned short idx1 = GetScene()->mp_shadow_volume_mesh[(lp*3)+1];
|
|
// unsigned short idx2 = GetScene()->mp_shadow_volume_mesh[(lp*3)+2];
|
|
//
|
|
// float x0 = p_xyz[(idx0*3)+0];
|
|
// float y0 = p_xyz[(idx0*3)+1];
|
|
// float z0 = p_xyz[(idx0*3)+2];
|
|
//
|
|
// float x1 = p_xyz[(idx1*3)+0];
|
|
// float y1 = p_xyz[(idx1*3)+1];
|
|
// float z1 = p_xyz[(idx1*3)+2];
|
|
//
|
|
// float x2 = p_xyz[(idx2*3)+0];
|
|
// float y2 = p_xyz[(idx2*3)+1];
|
|
// float z2 = p_xyz[(idx2*3)+2];
|
|
//
|
|
// float x3 = x0 + px;
|
|
// float y3 = y0 + py;
|
|
// float z3 = z0 + pz;
|
|
//
|
|
// float x4 = x1 + px;
|
|
// float y4 = y1 + py;
|
|
// float z4 = z1 + pz;
|
|
//
|
|
// float x5 = x2 + px;
|
|
// float y5 = y2 + py;
|
|
// float z5 = z2 + pz;
|
|
//
|
|
// GX::SetBlendMode ( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_FALSE, GX_TRUE, GX_FALSE );
|
|
//
|
|
// switch ( shape )
|
|
// {
|
|
// case 0:
|
|
// GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::End();
|
|
// GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::End();
|
|
// break;
|
|
// case 1:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::End();
|
|
// break;
|
|
// case 2:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::End();
|
|
// break;
|
|
// case 3:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::End();
|
|
// break;
|
|
// case 4:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::End();
|
|
// break;
|
|
// case 5:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::End();
|
|
// break;
|
|
// case 6:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::End();
|
|
// break;
|
|
// case 7:
|
|
// default:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 10 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::End();
|
|
// break;
|
|
// }
|
|
// GX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_FALSE, GX_TRUE, GX_FALSE );
|
|
//
|
|
// switch ( shape )
|
|
// {
|
|
// case 0:
|
|
// GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::End();
|
|
// GX::Begin( GX_TRIANGLES, GX_VTXFMT0, 3 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::End();
|
|
// break;
|
|
// case 1:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::End();
|
|
// break;
|
|
// case 2:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::End();
|
|
// break;
|
|
// case 3:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::End();
|
|
// break;
|
|
// case 4:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::End();
|
|
// break;
|
|
// case 5:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::End();
|
|
// break;
|
|
// case 6:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 8 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::End();
|
|
// break;
|
|
// case 7:
|
|
// default:
|
|
// GX::Begin( GX_TRIANGLESTRIP, GX_VTXFMT0, 10 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::Position3f32( x1, y1, z1 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x4, y4, z4 );
|
|
// GX::Position3f32( x3, y3, z3 );
|
|
// GX::Position3f32( x5, y5, z5 );
|
|
// GX::Position3f32( x0, y0, z0 );
|
|
// GX::Position3f32( x2, y2, z2 );
|
|
// GX::End();
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// delete p_xyz;
|
|
//#endif
|
|
// GX::SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
|
//// if ( !g_in_cutscene ) GX::SetClipMode( GX_CLIP_ENABLE );
|
|
// GX::SetProjectionv( p_pm );
|
|
// }
|
|
// else
|
|
{
|
|
GX::LoadNrmMtxImm((MtxPtr)&root, GX_PNMTX0);
|
|
// Render the scene & see if any meshes were drawn. If so, transform the
|
|
// vertex buffer for use when the GPU comes to actually render it..
|
|
NxNgc::EngineGlobals.poly_culling = false;
|
|
|
|
make_scene_visible( GetScene() );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_S16, 6 );
|
|
render_scene( GetScene(), mp_posNormRenderBuffer, render_flags | vRENDER_NO_CULLING );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT6, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
GX::SetVtxAttrFmt( GX_VTXFMT7, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( ( m_flags & CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED ) == 0 ) render_flags |= NxNgc::vRENDER_LIT;
|
|
GX::LoadNrmMtxImm((MtxPtr)&tr, GX_PNMTX0);
|
|
if ( GetScene()->m_numHierarchyObjects && GetBoneTransforms() )
|
|
{
|
|
// Car or something...
|
|
NxNgc::EngineGlobals.poly_culling = true;
|
|
make_scene_visible( GetScene() );
|
|
render_scene( GetScene(), NULL, render_flags | vRENDER_NO_CULLING, GetBoneTransforms(), GetTransform(), GetNumBones() );
|
|
}
|
|
else
|
|
{
|
|
if( ( m_flags & CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED ) == 0 ) render_flags |= NxNgc::vRENDER_LIT;
|
|
// No bones, just render normally. Must be a trashcan or something.
|
|
NxNgc::EngineGlobals.poly_culling = false;
|
|
make_scene_visible( GetScene() );
|
|
// int meshes_rendered = cull_scene( GetScene(), vRENDER_OCCLUDED, GetTransform() );
|
|
render_scene( GetScene(), NULL, render_flags );
|
|
// SetMeshesRendered( meshes_rendered );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void process_instances( void )
|
|
{
|
|
current_index = 0;
|
|
|
|
if ( g_mc_hack ) return;
|
|
|
|
// Seed the static pointer off to NULL, otherwise if there is only one object with bone transforms, it will never update.
|
|
pLastBoneTransforms = NULL;
|
|
|
|
// First go through and build a list of the visible instances.
|
|
CInstance *p_instance = pFirstInstance;
|
|
while( p_instance )
|
|
{
|
|
#ifndef __NOPT_FINAL__
|
|
p_instance->m_object_num = g_object;
|
|
g_object++;
|
|
#endif // __NOPT_FINAL__
|
|
if( p_instance->GetActive() && p_instance->GetScene()->mp_scene_data )
|
|
{
|
|
p_instances[current_index++] = p_instance;
|
|
}
|
|
p_instance = p_instance->GetNextInstance();
|
|
}
|
|
|
|
int save_g_object = g_object;
|
|
|
|
// Now sort the list based on bone transform and number of semitransparent objects in scene.
|
|
if( current_index > 0 )
|
|
{
|
|
if( current_index > 1 ) qsort( p_instances, current_index, sizeof( CInstance* ), sort_by_bone_transform );
|
|
|
|
int i = 0;
|
|
Mth::Matrix *pLast = NULL;
|
|
ROMtx bone_mtx[60];
|
|
|
|
for( ; i < current_index; ++i )
|
|
{
|
|
#ifndef __NOPT_FINAL__
|
|
g_object = p_instances[i]->m_object_num;
|
|
#endif // __NOPT_FINAL__
|
|
|
|
if(( p_instances[i]->GetBoneTransforms() == NULL ) || ( p_instances[i]->GetScene()->m_numHierarchyObjects > 0 ))
|
|
break;
|
|
|
|
p_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, bone_mtx, pLast );
|
|
pLast = p_instances[i]->GetBoneTransforms();
|
|
}
|
|
|
|
// for( ; i < current_index; ++i )
|
|
// {
|
|
//#ifndef __NOPT_FINAL__
|
|
// g_object = p_instances[i]->m_object_num;
|
|
//#endif // __NOPT_FINAL__
|
|
//
|
|
// p_instances[i]->Transform( 0 /*flags*/ | vRENDER_OPAQUE | vRENDER_SEMITRANSPARENT, NULL, NULL );
|
|
// }
|
|
}
|
|
g_object = save_g_object;
|
|
}
|
|
|
|
|
|
|
|
s16 *CInstance::GetPosNormalBuffer( int buffer )
|
|
{
|
|
int num_vertex = mp_scene->mp_dl->mp_object_header->m_num_skin_verts;
|
|
Dbg_MsgAssert(num_vertex, ("No verts in scene."));
|
|
|
|
s16 * rv = (s16*)NsBuffer::alloc( sizeof(s16) * 6 * (num_vertex+1) );
|
|
return rv;
|
|
}
|
|
|
|
CInstance::CInstance( sScene *pScene, Mth::Matrix &transform, int numBones, Mth::Matrix *pBoneTransforms )
|
|
{
|
|
SetTransform( transform );
|
|
mp_bone_transforms = pBoneTransforms;
|
|
m_num_bones = numBones;
|
|
mp_scene = pScene;
|
|
m_active = true;
|
|
m_flags = 0;
|
|
mp_model = NULL;
|
|
|
|
mp_next_instance = pFirstInstance;
|
|
pFirstInstance = this;
|
|
|
|
mp_posNormBuffer = NULL;
|
|
m_visibility_mask = 0xff;
|
|
|
|
// Check to see whether this instance is allowed to be lit or not (for non-skinned instances).
|
|
// Currently, we assume that instances with a model containing valid normals requires lighting, except in the
|
|
// situation where that model contains a mesh specifically flagged not to be lit.
|
|
if(( pBoneTransforms == NULL ) || ( GetScene()->m_numHierarchyObjects > 0 ))
|
|
{
|
|
for( int m = 0; m < pScene->m_num_filled_meshes; ++m )
|
|
{
|
|
NxNgc::sMesh *p_mesh = pScene->mpp_mesh_list[m];
|
|
if( !pScene->mp_scene_data->m_num_nrm )
|
|
return;
|
|
if( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<7) )
|
|
return;
|
|
}
|
|
m_flags |= CInstance::INSTANCE_FLAG_LIGHTING_ALLOWED;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
CInstance::~CInstance()
|
|
{
|
|
if( m_flags & INSTANCE_FLAG_DELETE_ATTACHED_SCENE )
|
|
{
|
|
if( mp_scene )
|
|
{
|
|
delete mp_scene;
|
|
mp_scene = NULL;
|
|
}
|
|
}
|
|
|
|
// if ( mp_posNormBuffer )
|
|
// {
|
|
// delete mp_posNormBuffer;
|
|
// mp_posNormBuffer = NULL;
|
|
// }
|
|
|
|
// Remove this instance from the list.
|
|
CInstance **pp_instance = &pFirstInstance;
|
|
while( *pp_instance )
|
|
{
|
|
if( *pp_instance == this )
|
|
{
|
|
*pp_instance = mp_next_instance;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pp_instance = &(( *pp_instance )->mp_next_instance );
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace NxNgc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|