mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
2831 lines
92 KiB
C++
2831 lines
92 KiB
C++
|
#include <sys/profiler.h>
|
||
|
#include <core/defines.h>
|
||
|
#include <core/debug.h>
|
||
|
#include <core/HashTable.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "nx_init.h"
|
||
|
#include "scene.h"
|
||
|
#include "render.h"
|
||
|
#include <gfx\ngc\p_nxgeom.h>
|
||
|
#include <gfx\nxflags.h>
|
||
|
#include "occlude.h"
|
||
|
#include "gfx/ngc/nx/mesh.h"
|
||
|
#include "charpipeline\skinning.h"
|
||
|
#include "gfx\NxMiscFX.h"
|
||
|
|
||
|
#include <sys/ngc\p_camera.h>
|
||
|
#include <sys/ngc\p_frame.h>
|
||
|
#include <sys/ngc\p_prim.h>
|
||
|
#include <sys/ngc\p_render.h>
|
||
|
|
||
|
#include "dolphin/base/ppcwgpipe.h"
|
||
|
#include "dolphin/gx/gxvert.h"
|
||
|
|
||
|
extern int g_object;
|
||
|
extern int g_view_object;
|
||
|
extern int g_material;
|
||
|
extern NxNgc::sScene * g_view_scene;
|
||
|
|
||
|
//extern u16 colorMap[];
|
||
|
|
||
|
bool g_skip_correctable = 0;
|
||
|
|
||
|
#define SHADOW_TEXTURE_SIZE 256
|
||
|
extern uint8 * shadowTextureData;
|
||
|
extern uint16 shadowPalette[16];
|
||
|
extern uint8 * zTextureData;
|
||
|
extern uint8 * blurTextureData;
|
||
|
NxNgc::sMaterial * p_last_material = NULL;
|
||
|
uint32 last_color_override = 0;
|
||
|
uint16 last_mesh_flags = 0;
|
||
|
bool last_correct = true;
|
||
|
bool reload_camera = false;
|
||
|
|
||
|
Mtx g_matrix0;
|
||
|
Mtx g_matrix90;
|
||
|
Mtx g_matrix180;
|
||
|
Mtx g_matrix270;
|
||
|
|
||
|
Mth::Vector g_shadow_object_pos;
|
||
|
|
||
|
int g_kill_layer = -1;
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
extern void FakeEnvMap( ROMtx m, s16 * srcPos, s16 * srcNorm, float * dstBase, u32 count );
|
||
|
extern void FakeEnvMapSkin( ROMtx m, s16 * srcPosNorm, float * dstBase, u32 count );
|
||
|
extern void FakeEnvMapFloat( ROMtx m, float * srcPos, s16 * srcNorm, float * dstBase, u32 count );
|
||
|
}
|
||
|
|
||
|
static float * sLastUV = NULL;
|
||
|
|
||
|
static bool first_mat = false;
|
||
|
//static bool one_mat = false;
|
||
|
|
||
|
extern uint16 shadowPalette[16];
|
||
|
|
||
|
//bool gOverDraw = false;
|
||
|
|
||
|
bool gMeshUseCorrection = false;
|
||
|
bool gMeshUseAniso = false;
|
||
|
|
||
|
const float CORRECTION_CUTOFF = ( 25.0f * 12.0f );
|
||
|
const float ANISO_CUTOFF = ( 100.0f * 12.0f );
|
||
|
|
||
|
int meshes_considered = 0;
|
||
|
|
||
|
namespace NxNgc
|
||
|
{
|
||
|
|
||
|
Lst::HashTable< sTextureProjectionDetails > *pTextureProjectionDetailsTable = NULL;
|
||
|
|
||
|
NsCamera current_cam;
|
||
|
|
||
|
#ifdef SHORT_VERT
|
||
|
static void cam_offset( float x, float y, float z )
|
||
|
{
|
||
|
Mtx m;
|
||
|
|
||
|
MTXTrans( m, x, y, z );
|
||
|
MTXConcat( EngineGlobals.current_uploaded, m, m );
|
||
|
|
||
|
GX::LoadPosMtxImm( m, GX_PNMTX0 );
|
||
|
}
|
||
|
#endif // SHORT_VERT
|
||
|
|
||
|
//static void reflect_uvs( sMesh * p_mesh, float * p_tex, s16 * p_posBuffer, s16 * p_normBuffer, int step )
|
||
|
//{
|
||
|
// if ( sLastUV == p_tex ) return;
|
||
|
//
|
||
|
// // Inverse transform the camera position by the local to world matrix.
|
||
|
// NsMatrix mp;
|
||
|
//// NsMatrix mi;
|
||
|
//
|
||
|
// mp.copy( *((NsMatrix*)EngineGlobals.current_uploaded) );
|
||
|
//// mp.copy( EngineGlobals.camera );
|
||
|
//#ifdef SHORT_VERT
|
||
|
// NsVector v( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );
|
||
|
// mp.translate( &v, NsMatrix_Combine_Post );
|
||
|
//#endif // SHORT_VERT
|
||
|
//// mi.invert( mp );
|
||
|
//// mp.setRight( mi.getRight() );
|
||
|
//// mp.setUp( mi.getUp() );
|
||
|
//// mp.setAt( mi.getAt() );
|
||
|
//
|
||
|
//// mp.invert();
|
||
|
//
|
||
|
//// mp.setPosX( mi.getPosX() );
|
||
|
//// mp.setPosY( mi.getPosY() );
|
||
|
//// mp.setPosZ( mi.getPosZ() );
|
||
|
//
|
||
|
// ROMtx sm;
|
||
|
//
|
||
|
// sm[0][0] = mp.getRightX();
|
||
|
// sm[1][0] = mp.getRightY();
|
||
|
// sm[2][0] = mp.getRightZ();
|
||
|
//
|
||
|
// sm[0][1] = mp.getUpX();
|
||
|
// sm[1][1] = mp.getUpY();
|
||
|
// sm[2][1] = mp.getUpZ();
|
||
|
//
|
||
|
// sm[0][2] = mp.getAtX();
|
||
|
// sm[1][2] = mp.getAtY();
|
||
|
// sm[2][2] = mp.getAtZ();
|
||
|
//
|
||
|
// sm[3][0] = mp.getPosX();
|
||
|
// sm[3][1] = mp.getPosY();
|
||
|
// sm[3][2] = mp.getPosZ();
|
||
|
//
|
||
|
// if ( step == 6 )
|
||
|
// {
|
||
|
// // Skinned
|
||
|
// FakeEnvMapSkin( sm, p_posBuffer, p_tex, p_mesh->m_num_vertex );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// // Not Skinned
|
||
|
// GQRSetup6( p_mesh->m_vertex_format - 1, // Pos
|
||
|
// GQR_TYPE_S16,
|
||
|
// 0, // UV
|
||
|
// GQR_TYPE_F32 );
|
||
|
//
|
||
|
// GQRSetup7( 14, // Normal
|
||
|
// GQR_TYPE_S16,
|
||
|
// 0, // UV
|
||
|
// GQR_TYPE_F32 );
|
||
|
//
|
||
|
//// NsMatrix mn;
|
||
|
//// mn.copy( mp );
|
||
|
////// mn.invert(;
|
||
|
//// mn.setPos( 0.0f, 0.0f, 0.0f );
|
||
|
////
|
||
|
//// float shift = (float)(1<<(p_mesh->m_vertex_format-1));
|
||
|
//// for ( int lp = 0; lp < p_mesh->m_num_vertex; lp++ )
|
||
|
//// {
|
||
|
//// NsVector in, tpos, tnorm;
|
||
|
//// in.x = (((float)p_posBuffer[(lp*3)+0])/shift);
|
||
|
//// in.y = (((float)p_posBuffer[(lp*3)+1])/shift);
|
||
|
//// in.z = (((float)p_posBuffer[(lp*3)+2])/shift);
|
||
|
//// mp.multiply( &in, &tpos );
|
||
|
//// in.x = (((float)p_normBuffer[(lp*3)+0])/(float)(1<<14));
|
||
|
//// in.y = (((float)p_normBuffer[(lp*3)+1])/(float)(1<<14));
|
||
|
//// in.z = (((float)p_normBuffer[(lp*3)+2])/(float)(1<<14));
|
||
|
//// mn.multiply( &in, &tnorm );
|
||
|
////// float z1 = 1.0f / 2000.0f;
|
||
|
////// p_tex[(lp*2)+0] = ( ( ( ( ( tpos.x / (tpos.z+(float)gAdd) ) * (float)gScale ) + tnorm.x ) + 1.0f ) * 0.5f ) * (float)gRepeat;
|
||
|
////// p_tex[(lp*2)+1] = ( ( ( ( ( tpos.y / (tpos.z+(float)gAdd) ) * (float)gScale ) + tnorm.y ) + 1.0f ) * 0.5f ) * (float)gRepeat;
|
||
|
////
|
||
|
//// p_tex[(lp*2)+0] = ( ( ( ( ( tpos.x / ( tpos.z > 1 ? 1 : tpos.z ) ) + tnorm.x ) * 1.0f ) * 0.5f ) + 0.5f );
|
||
|
//// p_tex[(lp*2)+1] = ( ( ( ( ( tpos.y / ( tpos.z > 1 ? 1 : tpos.z ) ) + tnorm.y ) * 1.0f ) * 0.5f ) + 0.5f );
|
||
|
////
|
||
|
////// p_tex[(lp*2)+0] = ( ( ( ( tpos.x + ( tnorm.x * tpos.z ) ) * ( 0.5f * tpos.z ) ) * ( 3.0f * tpos.z ) ) + ( 0.5f * tpos.z ) );
|
||
|
////// p_tex[(lp*2)+1] = ( ( ( ( tpos.y + ( tnorm.y * tpos.z ) ) * ( 0.5f * tpos.z ) ) * ( 3.0f * tpos.z ) ) + ( 0.5f * tpos.z ) );
|
||
|
////
|
||
|
////// p_tex[(lp*2)+0] = ( ( tnorm.x ) + 1.0f ) * 0.5f;
|
||
|
////// p_tex[(lp*2)+1] = ( ( tnorm.y ) + 1.0f ) * 0.5f;
|
||
|
//// }
|
||
|
//
|
||
|
// FakeEnvMap( sm, p_posBuffer, p_normBuffer, p_tex, p_mesh->m_num_vertex );
|
||
|
//
|
||
|
// // GQR back to normal.
|
||
|
// GQRSetup7( GQR_SCALE_128, // Pos/Normal
|
||
|
// GQR_TYPE_S16,
|
||
|
// GQR_SCALE_128,
|
||
|
// GQR_TYPE_S16 );
|
||
|
// GQRSetup6( GQR_SCALE_256, // Weights
|
||
|
// GQR_TYPE_U8,
|
||
|
// GQR_SCALE_256,
|
||
|
// GQR_TYPE_U8 );
|
||
|
// }
|
||
|
// sLastUV = p_tex;
|
||
|
//}
|
||
|
|
||
|
#ifndef SHORT_VERT
|
||
|
//static void float_reflect_uvs( sMesh * p_mesh, float * p_tex, float * p_posBuffer, s16 * p_normBuffer, int step )
|
||
|
//{
|
||
|
// if ( sLastUV == p_tex ) return;
|
||
|
//
|
||
|
// // Inverse transform the camera position by the local to world matrix.
|
||
|
// NsMatrix mp;
|
||
|
//
|
||
|
// mp.copy( *((NsMatrix*)EngineGlobals.current_uploaded) );
|
||
|
//
|
||
|
// ROMtx sm;
|
||
|
//
|
||
|
// sm[0][0] = mp.getRightX();
|
||
|
// sm[1][0] = mp.getRightY();
|
||
|
// sm[2][0] = mp.getRightZ();
|
||
|
//
|
||
|
// sm[0][1] = mp.getUpX();
|
||
|
// sm[1][1] = mp.getUpY();
|
||
|
// sm[2][1] = mp.getUpZ();
|
||
|
//
|
||
|
// sm[0][2] = mp.getAtX();
|
||
|
// sm[1][2] = mp.getAtY();
|
||
|
// sm[2][2] = mp.getAtZ();
|
||
|
//
|
||
|
// sm[3][0] = mp.getPosX();
|
||
|
// sm[3][1] = mp.getPosY();
|
||
|
// sm[3][2] = mp.getPosZ();
|
||
|
//
|
||
|
//// GQRSetup6( 0, // Pos
|
||
|
//// GQR_TYPE_F32,
|
||
|
//// 0, // UV
|
||
|
//// GQR_TYPE_F32 );
|
||
|
////
|
||
|
//// GQRSetup7( 14, // Normal
|
||
|
//// GQR_TYPE_S16,
|
||
|
//// 0, // UV
|
||
|
//// GQR_TYPE_F32 );
|
||
|
//
|
||
|
// FakeEnvMapFloat( sm, p_posBuffer, p_normBuffer, p_tex, p_mesh->m_num_vertex );
|
||
|
//
|
||
|
//// // GQR back to normal.
|
||
|
//// GQRSetup7( GQR_SCALE_128, // Pos/Normal
|
||
|
//// GQR_TYPE_S16,
|
||
|
//// GQR_SCALE_128,
|
||
|
//// GQR_TYPE_S16 );
|
||
|
//// GQRSetup6( GQR_SCALE_256, // Weights
|
||
|
//// GQR_TYPE_U8,
|
||
|
//// GQR_SCALE_256,
|
||
|
//// GQR_TYPE_U8 );
|
||
|
// sLastUV = p_tex;
|
||
|
//}
|
||
|
#endif // SHORT_VERT
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void init_render_system( void )
|
||
|
{
|
||
|
pTextureProjectionDetailsTable = new Lst::HashTable< sTextureProjectionDetails >( 8 );
|
||
|
|
||
|
MTXRotDeg( g_matrix0, 'y', 0.0f );
|
||
|
MTXRotDeg( g_matrix90, 'y', 90.0f );
|
||
|
MTXRotDeg( g_matrix180, 'y', 180.0f );
|
||
|
MTXRotDeg( g_matrix270, 'y', 270.0f );
|
||
|
}
|
||
|
|
||
|
void set_blend_mode( uint64 mode )
|
||
|
{
|
||
|
// Low 32 bits contain the mode, high 32 bits contain the fixed alpha value.
|
||
|
uint32 actual_mode = (uint32)mode;
|
||
|
// uint32 fixed_alpha = (uint32)( mode >> 32 );
|
||
|
|
||
|
// Only do something if the blend mode is changing.
|
||
|
// if( actual_mode != EngineGlobals.blend_mode_value )
|
||
|
{
|
||
|
switch( actual_mode )
|
||
|
{
|
||
|
case vBLEND_MODE_ADD:
|
||
|
case vBLEND_MODE_ADD_FIXED:
|
||
|
GX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
case vBLEND_MODE_SUBTRACT:
|
||
|
case vBLEND_MODE_SUB_FIXED:
|
||
|
GX::SetBlendMode ( GX_BM_SUBTRACT, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
case vBLEND_MODE_BLEND:
|
||
|
case vBLEND_MODE_BLEND_FIXED:
|
||
|
GX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
case vBLEND_MODE_BRIGHTEN:
|
||
|
case vBLEND_MODE_BRIGHTEN_FIXED:
|
||
|
GX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
case vBLEND_MODE_MODULATE_FIXED:
|
||
|
case vBLEND_MODE_MODULATE:
|
||
|
GX::SetBlendMode ( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
case vBLEND_MODE_DIFFUSE:
|
||
|
default:
|
||
|
GX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void set_render_state( uint32 type, uint32 state )
|
||
|
{
|
||
|
switch( type )
|
||
|
{
|
||
|
case RS_ZWRITEENABLE:
|
||
|
{
|
||
|
if( state > 0 )
|
||
|
{
|
||
|
if( EngineGlobals.z_write_enabled == FALSE )
|
||
|
{
|
||
|
GX::SetZMode ( EngineGlobals.z_test_enabled ? GX_TRUE : GX_FALSE, EngineGlobals.z_test_enabled ? GX_LEQUAL : GX_ALWAYS, GX_TRUE );
|
||
|
EngineGlobals.z_write_enabled = TRUE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( EngineGlobals.z_write_enabled == TRUE )
|
||
|
{
|
||
|
GX::SetZMode ( EngineGlobals.z_test_enabled ? GX_TRUE : GX_FALSE, EngineGlobals.z_test_enabled ? GX_LEQUAL : GX_ALWAYS, GX_FALSE );
|
||
|
EngineGlobals.z_write_enabled = FALSE;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case RS_ZTESTENABLE:
|
||
|
{
|
||
|
if( state > 0 )
|
||
|
{
|
||
|
if( EngineGlobals.z_test_enabled == FALSE )
|
||
|
{
|
||
|
GX::SetZMode ( GX_TRUE, GX_LEQUAL, EngineGlobals.z_write_enabled ? GX_TRUE : GX_FALSE );
|
||
|
EngineGlobals.z_test_enabled = TRUE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( EngineGlobals.z_test_enabled == TRUE )
|
||
|
{
|
||
|
GX::SetZMode ( GX_FALSE, GX_ALWAYS, EngineGlobals.z_write_enabled ? GX_TRUE : GX_FALSE );
|
||
|
EngineGlobals.z_test_enabled = FALSE;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case RS_ALPHACUTOFF:
|
||
|
{
|
||
|
// GX::SetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );
|
||
|
// // Convert from state (where 1 means "render all pixels with alpha 1 or higher") to the D3D
|
||
|
// if( state != EngineGlobals.alpha_ref )
|
||
|
// {
|
||
|
// EngineGlobals.alpha_ref = state;
|
||
|
// if( state > 0 )
|
||
|
// {
|
||
|
// D3DDevice_SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
|
||
|
// D3DDevice_SetRenderState( D3DRS_ALPHAREF, state );
|
||
|
// D3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// D3DDevice_SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
|
||
|
// }
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
float frustum_sort_mid( Mth::Vector& p_sphere )
|
||
|
{
|
||
|
NsVector test_in;
|
||
|
NsVector test_mid;
|
||
|
|
||
|
// D3DXMATRIX *p_world_transform;
|
||
|
//
|
||
|
// // Build the composite transform if required.
|
||
|
// if( p_bbox_transform )
|
||
|
// {
|
||
|
// p_world_transform = p_bbox_transform;
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// p_world_transform = NULL;
|
||
|
// }
|
||
|
|
||
|
test_in.x = p_sphere[X];
|
||
|
test_in.y = p_sphere[Y];
|
||
|
test_in.z = p_sphere[Z];
|
||
|
|
||
|
EngineGlobals.local_to_camera.multiply( &test_in, &test_mid );
|
||
|
|
||
|
// if( p_world_transform )
|
||
|
// {
|
||
|
// D3DXVec3Transform( &test_mid, &test_in, p_world_transform );
|
||
|
// test_in.x = test_mid.x;
|
||
|
// test_in.y = test_mid.y;
|
||
|
// test_in.z = test_mid.z;
|
||
|
// }
|
||
|
// D3DXVec3Transform( &test_mid, &test_in, &EngineGlobals.view_matrix );
|
||
|
return test_mid.z;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
struct sSortedMeshEntry
|
||
|
{
|
||
|
sMesh *p_mesh;
|
||
|
float sort;
|
||
|
sSortedMeshEntry *pNext;
|
||
|
};
|
||
|
|
||
|
|
||
|
//static sSortedMeshEntry sortedMeshArray[1000];
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
static int cmp( const void *p1, const void *p2 )
|
||
|
{
|
||
|
return((sSortedMeshEntry*)p1)->sort < ((sSortedMeshEntry*)p2)->sort ? -1 : ((sSortedMeshEntry*)p1)->sort > ((sSortedMeshEntry*)p2)->sort ? 1 : 0;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void create_texture_projection_details( sTexture *p_texture, Nx::CNgcModel *p_model, sScene *p_scene )
|
||
|
{
|
||
|
sTextureProjectionDetails *p_details = new sTextureProjectionDetails;
|
||
|
|
||
|
p_details->p_model = p_model;
|
||
|
p_details->p_scene = p_scene;
|
||
|
p_details->p_texture = p_texture;
|
||
|
|
||
|
// Flag this scene as receiving shadows.
|
||
|
// p_scene->m_flags |= SCENE_FLAG_RECEIVE_SHADOWS;
|
||
|
|
||
|
pTextureProjectionDetailsTable->PutItem((uint32)p_texture, p_details );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void destroy_texture_projection_details( sTexture *p_texture )
|
||
|
{
|
||
|
sTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );
|
||
|
if( p_details )
|
||
|
{
|
||
|
pTextureProjectionDetailsTable->FlushItem((uint32)p_texture );
|
||
|
delete p_details;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void set_texture_projection_camera( sTexture *p_texture, NsVector * p_pos, NsVector * p_at )
|
||
|
{
|
||
|
// NsMatrix view_matrix;
|
||
|
|
||
|
sTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->GetItem((uint32)p_texture );
|
||
|
if( p_details )
|
||
|
{
|
||
|
NsVector up;
|
||
|
// Check for 'straight down' vector.
|
||
|
if(( p_pos->x == p_at->x ) && ( p_pos->z == p_at->z ))
|
||
|
{
|
||
|
// D3DXMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &D3DXVECTOR3( 0.0f, 0.0f, 1.0f ));
|
||
|
|
||
|
|
||
|
up.set( 0.0f, 0.0f, 1.0f );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
up.set( 0.0f, 1.0f, 0.0f );
|
||
|
// D3DXMatrixLookAtRH( &p_details->view_matrix, p_pos, p_at, &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));
|
||
|
}
|
||
|
|
||
|
// Get the 'right' vector as the cross product of camera 'at and world 'up'.
|
||
|
// NsVector screen_right;
|
||
|
// NsVector screen_up;
|
||
|
// screen_right.cross( *p_at, up );
|
||
|
// screen_up.cross( screen_right, *p_at );
|
||
|
//
|
||
|
// screen_right.normalize();
|
||
|
// screen_up.normalize();
|
||
|
//
|
||
|
// p_details->view_matrix.setRight( &screen_right );
|
||
|
// p_details->view_matrix.setUp( &screen_up );
|
||
|
// p_details->view_matrix.setAt( p_at );
|
||
|
// p_details->view_matrix.setPos( p_pos );
|
||
|
p_details->view_matrix.lookAt( p_pos, &up, p_at );
|
||
|
|
||
|
|
||
|
|
||
|
// D3DXMatrixOrthoRH( &p_details->projection_matrix, 96.0f, 96.0f, 1.0f, 512.0f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
//static D3DXMATRIX world;
|
||
|
//static D3DXMATRIX view;
|
||
|
//static D3DXMATRIX projection;
|
||
|
|
||
|
void set_camera( Mth::Matrix *p_matrix, Mth::Vector *p_position, float screen_angle, float aspect_ratio, float scale )
|
||
|
{
|
||
|
NsMatrix m;
|
||
|
NsFrame f;
|
||
|
|
||
|
EngineGlobals.tx = 2.0f * tanf(screen_angle*8.72664626e-03f); // tan of half (angle in radians)
|
||
|
EngineGlobals.ty = -(EngineGlobals.tx / aspect_ratio);
|
||
|
EngineGlobals.near = -2.0;
|
||
|
EngineGlobals.far = -40000.0;
|
||
|
|
||
|
current_cam.perspective( EngineGlobals.tx, -EngineGlobals.ty, -EngineGlobals.near, -EngineGlobals.far * 2 );
|
||
|
|
||
|
// if ( scale > 1.0f )
|
||
|
// {
|
||
|
// current_cam.SetViewMatrix( 2, 2, -0.999999f );
|
||
|
// current_cam.SetViewMatrix( 3, 2, 0.0f );
|
||
|
// }
|
||
|
|
||
|
EngineGlobals.tx = tanf( Mth::DegToRad( screen_angle * 0.5f )); ; // tan of half (angle in radians)
|
||
|
EngineGlobals.ty = -(EngineGlobals.tx / aspect_ratio);
|
||
|
EngineGlobals.sx = 1.0f/sqrtf(1.0f+1.0f/(EngineGlobals.tx*EngineGlobals.tx));
|
||
|
EngineGlobals.sy = 1.0f/sqrtf(1.0f+1.0f/(EngineGlobals.ty*EngineGlobals.ty));
|
||
|
EngineGlobals.cx = 1.0f/sqrtf(1.0f+EngineGlobals.tx*EngineGlobals.tx);
|
||
|
EngineGlobals.cy = 1.0f/sqrtf(1.0f+EngineGlobals.ty*EngineGlobals.ty);
|
||
|
// EngineGlobals.near = -2.0;
|
||
|
// EngineGlobals.far = -40000.0;
|
||
|
|
||
|
m.setRight( -p_matrix->GetRight().GetX(), -p_matrix->GetRight().GetY(), -p_matrix->GetRight().GetZ() );
|
||
|
m.setUp( p_matrix->GetUp().GetX(), p_matrix->GetUp().GetY(), p_matrix->GetUp().GetZ() );
|
||
|
m.setAt( -p_matrix->GetAt().GetX(), -p_matrix->GetAt().GetY(), -p_matrix->GetAt().GetZ() );
|
||
|
m.setPos( p_position->GetX(), p_position->GetY(), p_position->GetZ() );
|
||
|
|
||
|
f.setModelMatrix( &m );
|
||
|
current_cam.setFrame( &f );
|
||
|
current_cam.begin(); // No need to end...
|
||
|
|
||
|
EngineGlobals.world_to_camera = *current_cam.getCurrent();
|
||
|
EngineGlobals.local_to_camera = *current_cam.getCurrent();
|
||
|
EngineGlobals.camera = m;
|
||
|
|
||
|
EngineGlobals.object_pos.x = 0.0f;
|
||
|
EngineGlobals.object_pos.y = 0.0f;
|
||
|
EngineGlobals.object_pos.z = 0.0f;
|
||
|
|
||
|
MTXCopy ( (MtxPtr)current_cam.getCurrent(), EngineGlobals.current_uploaded );
|
||
|
|
||
|
|
||
|
// NsVector wscale( 1.0f, 1.0f, 1.0f ); //scale, scale, scale );
|
||
|
NsVector wscale( scale, scale, scale );
|
||
|
NsMatrix ms;
|
||
|
ms.copy( m );
|
||
|
ms.scale( &wscale, NsMatrix_Combine_Pre );
|
||
|
|
||
|
f.setModelMatrix( &ms );
|
||
|
current_cam.setFrame( &f );
|
||
|
current_cam.end();
|
||
|
current_cam.begin(); // No need to end...
|
||
|
|
||
|
// NsMatrix ms;
|
||
|
// ms.setRight( m.getRightX() * scale, m.getRightY() * scale, m.getRightZ() * scale );
|
||
|
// ms.setUp( m.getUpX() * scale, m.getUpY() * scale, m.getUpZ() * scale );
|
||
|
// ms.setAt( m.getAtX() * scale, m.getAtY() * scale, m.getAtZ() * scale );
|
||
|
// ms.setPos( m.getPosX(), m.getPosY(), m.getPosZ() );
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* Checks a bounding box against the current view frustum */
|
||
|
/* (iBgnoring far clipping), */
|
||
|
/* returns true if any part is visible. */
|
||
|
/* Horribly inefficient at present. */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
bool frustum_check_box( Mtx m, Mth::CBBox& box )
|
||
|
{
|
||
|
Vec test_in, test_out;
|
||
|
|
||
|
uint32 cumulative_projection_space_outcode = 0xFF;
|
||
|
float min_x = box.GetMin().GetX();
|
||
|
float min_y = box.GetMin().GetY();
|
||
|
float min_z = box.GetMin().GetZ();
|
||
|
float max_x = box.GetMax().GetX();
|
||
|
float max_y = box.GetMax().GetY();
|
||
|
float max_z = box.GetMax().GetZ();
|
||
|
|
||
|
for( uint32 v = 0; v < 8; ++v )
|
||
|
{
|
||
|
uint32 projection_space_outcode = 0;
|
||
|
|
||
|
test_in.x = ( v & 0x04 ) ? max_x : min_x;
|
||
|
test_in.y = ( v & 0x02 ) ? max_y : min_y;
|
||
|
test_in.z = ( v & 0x01 ) ? max_z : min_z;
|
||
|
|
||
|
// At this point it's important to check to see whether the point is in postive or negative z-space, since
|
||
|
// after the projection transform, both very large camera space z values and camera space z values where z < 0
|
||
|
// will give results with z > 1. (Camera space values in the range [0,near] give negative projection space z values).
|
||
|
MTXMultVec( m, &test_in, &test_out );
|
||
|
|
||
|
// if(( -test_mid.z < 0.0f ) && ( !EngineGlobals.is_orthographic ))
|
||
|
// {
|
||
|
// test_out.x = -test_out.x;
|
||
|
// test_out.y = -test_out.y;
|
||
|
// }
|
||
|
|
||
|
if( test_out.x > 1.0f )
|
||
|
{
|
||
|
projection_space_outcode |= 0x01;
|
||
|
}
|
||
|
else if( test_out.x < -1.0f )
|
||
|
{
|
||
|
projection_space_outcode |= 0x02;
|
||
|
}
|
||
|
|
||
|
if( test_out.y > 1.0f )
|
||
|
{
|
||
|
projection_space_outcode |= 0x04;
|
||
|
}
|
||
|
else if( test_out.y < -1.0f )
|
||
|
{
|
||
|
projection_space_outcode |= 0x08;
|
||
|
}
|
||
|
|
||
|
cumulative_projection_space_outcode &= projection_space_outcode;
|
||
|
|
||
|
if( cumulative_projection_space_outcode == 0 )
|
||
|
{
|
||
|
// Early out.
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool frustum_check_sphere( Mtx m, Mth::Vector& p_sphere )
|
||
|
{
|
||
|
// Vec in;
|
||
|
// Vec out;
|
||
|
//
|
||
|
// in.x = p_sphere[X];
|
||
|
// in.y = p_sphere[Y];
|
||
|
// in.z = p_sphere[Z];
|
||
|
//
|
||
|
//// NsMatrix mat;
|
||
|
//// mat.copy( EngineGlobals.local_to_camera );
|
||
|
//// NsVector s( 0.5f, 0.5f, 0.5f );
|
||
|
//// mat.scale( &s, NsMatrix_Combine_Post );
|
||
|
////
|
||
|
////
|
||
|
//// mat.multiply( &in, &out );
|
||
|
//// EngineGlobals.local_to_camera.multiply( &in, &out );
|
||
|
//
|
||
|
// MTXMultVec( m, &in, &out );
|
||
|
//
|
||
|
// float x = out.x;
|
||
|
// float y = out.y;
|
||
|
// float z = out.z;
|
||
|
// float R = p_sphere[W];
|
||
|
//
|
||
|
// if ( R < ( z - EngineGlobals.near ) ) return false;
|
||
|
// if ( R < ( EngineGlobals.far - z ) ) return false;
|
||
|
//
|
||
|
// float sx_z = EngineGlobals.sx * z;
|
||
|
// float cx_x = EngineGlobals.cx * x;
|
||
|
// if ( R < ( sx_z - cx_x ) ) return false;
|
||
|
// if ( R < ( sx_z + cx_x ) ) return false;
|
||
|
//
|
||
|
// float sy_z = EngineGlobals.sy * z;
|
||
|
// float cy_y = EngineGlobals.cy * y;
|
||
|
// if ( R < ( sy_z - cy_y ) ) return false;
|
||
|
// if ( R < ( sy_z + cy_y ) ) return false;
|
||
|
//
|
||
|
// return true;
|
||
|
|
||
|
Mth::CBBox bbox;
|
||
|
Mth::Vector p;
|
||
|
|
||
|
p.Set( p_sphere[X] + p_sphere[W], p_sphere[Y], p_sphere[Z] ); bbox.AddPoint( p );
|
||
|
p.Set( p_sphere[X] - p_sphere[W], p_sphere[Y], p_sphere[Z] ); bbox.AddPoint( p );
|
||
|
p.Set( p_sphere[X] , p_sphere[Y]+ p_sphere[W], p_sphere[Z] ); bbox.AddPoint( p );
|
||
|
p.Set( p_sphere[X] , p_sphere[Y]- p_sphere[W], p_sphere[Z] ); bbox.AddPoint( p );
|
||
|
p.Set( p_sphere[X] , p_sphere[Y], p_sphere[Z]+ p_sphere[W] ); bbox.AddPoint( p );
|
||
|
p.Set( p_sphere[X] , p_sphere[Y], p_sphere[Z]- p_sphere[W] ); bbox.AddPoint( p );
|
||
|
|
||
|
return frustum_check_box( m, bbox );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* Checks a bounding box against the current view frustum */
|
||
|
/* (iBgnoring far clipping), */
|
||
|
/* returns true if any part is visible. */
|
||
|
/* Horribly inefficient at present. */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
bool frustum_check_box( Mth::CBBox& box )
|
||
|
{
|
||
|
int lp;
|
||
|
unsigned int code;
|
||
|
unsigned int codeAND;
|
||
|
f32 rx[8], ry[8], rz[8];
|
||
|
f32 p[GX_PROJECTION_SZ];
|
||
|
f32 vp[GX_VIEWPORT_SZ];
|
||
|
u32 clip_x;
|
||
|
u32 clip_y;
|
||
|
u32 clip_w;
|
||
|
u32 clip_h;
|
||
|
float clip_l;
|
||
|
float clip_t;
|
||
|
float clip_r;
|
||
|
float clip_b;
|
||
|
MtxPtr view;
|
||
|
float minx, miny, minz;
|
||
|
float maxx, maxy, maxz;
|
||
|
|
||
|
GX::GetProjectionv( p );
|
||
|
GX::GetViewportv( vp );
|
||
|
GX::GetScissor ( &clip_x, &clip_y, &clip_w, &clip_h );
|
||
|
clip_l = (float)clip_x;
|
||
|
clip_t = (float)clip_y;
|
||
|
clip_r = (float)(clip_x + clip_w);
|
||
|
clip_b = (float)(clip_y + clip_h);
|
||
|
|
||
|
view = (MtxPtr)&EngineGlobals.local_to_camera;
|
||
|
|
||
|
minx = box.GetMin().GetX();
|
||
|
miny = box.GetMin().GetY();
|
||
|
minz = box.GetMin().GetZ();
|
||
|
maxx = box.GetMax().GetX();
|
||
|
maxy = box.GetMax().GetY();
|
||
|
maxz = box.GetMax().GetZ();
|
||
|
GX::Project ( minx, miny, minz, view, p, vp, &rx[0], &ry[0], &rz[0] );
|
||
|
GX::Project ( minx, maxy, minz, view, p, vp, &rx[1], &ry[1], &rz[1] );
|
||
|
GX::Project ( maxx, miny, minz, view, p, vp, &rx[2], &ry[2], &rz[2] );
|
||
|
GX::Project ( maxx, maxy, minz, view, p, vp, &rx[3], &ry[3], &rz[3] );
|
||
|
GX::Project ( minx, miny, maxz, view, p, vp, &rx[4], &ry[4], &rz[4] );
|
||
|
GX::Project ( minx, maxy, maxz, view, p, vp, &rx[5], &ry[5], &rz[5] );
|
||
|
GX::Project ( maxx, miny, maxz, view, p, vp, &rx[6], &ry[6], &rz[6] );
|
||
|
GX::Project ( maxx, maxy, maxz, view, p, vp, &rx[7], &ry[7], &rz[7] );
|
||
|
|
||
|
// Generate clip code. {page 178, Procedural Elements for Computer Graphics}
|
||
|
// 1001|1000|1010
|
||
|
// | |
|
||
|
// ----+----+----
|
||
|
// 0001|0000|0010
|
||
|
// | |
|
||
|
// ----+----+----
|
||
|
// 0101|0100|0110
|
||
|
// | |
|
||
|
//
|
||
|
// Addition: Bit 4 is used for z behind.
|
||
|
|
||
|
codeAND = 0x001f;
|
||
|
for ( lp = 0; lp < 8; lp++ ) {
|
||
|
// Only check x/y if z is valid (if z is invalid, the x/y values will be garbage).
|
||
|
if ( rz[lp] > 1.0f ) {
|
||
|
code = (1<<4);
|
||
|
} else {
|
||
|
code = 0;
|
||
|
if ( rx[lp] < clip_l ) code |= (1<<0);
|
||
|
if ( rx[lp] > clip_r ) code |= (1<<1);
|
||
|
if ( ry[lp] > clip_b ) code |= (1<<2);
|
||
|
if ( ry[lp] < clip_t ) code |= (1<<3);
|
||
|
}
|
||
|
codeAND &= code;
|
||
|
if ( !codeAND ) return true;
|
||
|
}
|
||
|
if ( !codeAND ) return true;
|
||
|
return false;
|
||
|
// m_cull.clipCodeAND = codeAND;
|
||
|
// // If any bits are set in the AND code, the object is invisible.
|
||
|
// if ( codeAND ) {
|
||
|
// m_cull.visible = 0;
|
||
|
// }
|
||
|
//
|
||
|
// return !m_cull.visible; // 0 = not culled, 1 = culled.
|
||
|
|
||
|
|
||
|
//
|
||
|
// NsVector test_in, test_out;
|
||
|
//
|
||
|
// uint32 cumulative_projection_space_outcode = 0xFF;
|
||
|
// float min_x = box.GetMin().GetX();
|
||
|
// float min_y = box.GetMin().GetY();
|
||
|
// float min_z = box.GetMin().GetZ();
|
||
|
// float max_x = box.GetMax().GetX();
|
||
|
// float max_y = box.GetMax().GetY();
|
||
|
// float max_z = box.GetMax().GetZ();
|
||
|
//
|
||
|
// for( uint32 v = 0; v < 8; ++v )
|
||
|
// {
|
||
|
// uint32 projection_space_outcode = 0;
|
||
|
//
|
||
|
// test_in.x = ( v & 0x04 ) ? max_x : min_x;
|
||
|
// test_in.y = ( v & 0x02 ) ? max_y : min_y;
|
||
|
// test_in.z = ( v & 0x01 ) ? max_z : min_z;
|
||
|
//
|
||
|
// // At this point it's important to check to see whether the point is in postive or negative z-space, since
|
||
|
// // after the projection transform, both very large camera space z values and camera space z values where z < 0
|
||
|
// // will give results with z > 1. (Camera space values in the range [0,near] give negative projection space z values).
|
||
|
// EngineGlobals.local_to_camera.multiply( &test_in, &test_out );
|
||
|
//// MTXMultVec( m, &test_in, &test_out );
|
||
|
//
|
||
|
//// if(( -test_mid.z < 0.0f ) && ( !EngineGlobals.is_orthographic ))
|
||
|
//// {
|
||
|
//// test_out.x = -test_out.x;
|
||
|
//// test_out.y = -test_out.y;
|
||
|
//// }
|
||
|
//
|
||
|
// if( test_out.x > 1.0f )
|
||
|
// {
|
||
|
// projection_space_outcode |= 0x01;
|
||
|
// }
|
||
|
// else if( test_out.x < -1.0f )
|
||
|
// {
|
||
|
// projection_space_outcode |= 0x02;
|
||
|
// }
|
||
|
//
|
||
|
// if( test_out.y > 1.0f )
|
||
|
// {
|
||
|
// projection_space_outcode |= 0x04;
|
||
|
// }
|
||
|
// else if( test_out.y < -1.0f )
|
||
|
// {
|
||
|
// projection_space_outcode |= 0x08;
|
||
|
// }
|
||
|
//
|
||
|
// cumulative_projection_space_outcode &= projection_space_outcode;
|
||
|
//
|
||
|
// if( cumulative_projection_space_outcode == 0 )
|
||
|
// {
|
||
|
// // Early out.
|
||
|
// return true;
|
||
|
// }
|
||
|
// }
|
||
|
// return false;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* Quick determination of if something is visible or not, uses */
|
||
|
/* the previously calculated s and c vectors and the */
|
||
|
/* WorldToCamera transform (note, no attempt is made to ensure */
|
||
|
/* this is the same camera that the object will eventually be */
|
||
|
/* rendered with. */
|
||
|
/******************************************************************/
|
||
|
bool IsVisible( Mth::Vector &sphere )
|
||
|
{
|
||
|
NsVector in;
|
||
|
NsVector out;
|
||
|
|
||
|
in.x = sphere.GetX();
|
||
|
in.y = sphere.GetY();
|
||
|
in.z = sphere.GetZ();
|
||
|
|
||
|
EngineGlobals.world_to_camera.multiply( &in, &out );
|
||
|
|
||
|
float x = out.x;
|
||
|
float y = out.y;
|
||
|
float z = out.z;
|
||
|
float R = sphere[W];
|
||
|
|
||
|
if( //( -z + R < EngineGlobals.near ) ||
|
||
|
// if ( R < ( -10000.0f/*EngineGlobals.far*/ - z ) ) return false;
|
||
|
( 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 ))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( TestSphereAgainstOccluders( &sphere ))
|
||
|
{
|
||
|
// Occluded.
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
// if (R<z-near || R<far-z || R<sy*z+cy*y || R<sy*z-cy*y || R<sx*z-cx*x || R<sx*z+cx*x) visible = false;
|
||
|
|
||
|
}
|
||
|
|
||
|
bool frustum_check_sphere( Mth::Vector& p_sphere )
|
||
|
{
|
||
|
NsVector in;
|
||
|
NsVector out;
|
||
|
|
||
|
in.x = p_sphere[X];
|
||
|
in.y = p_sphere[Y];
|
||
|
in.z = p_sphere[Z];
|
||
|
|
||
|
// NsMatrix mat;
|
||
|
// mat.copy( EngineGlobals.local_to_camera );
|
||
|
// NsVector s( 0.5f, 0.5f, 0.5f );
|
||
|
// mat.scale( &s, NsMatrix_Combine_Post );
|
||
|
//
|
||
|
//
|
||
|
// mat.multiply( &in, &out );
|
||
|
EngineGlobals.local_to_camera.multiply( &in, &out );
|
||
|
|
||
|
float x = out.x;
|
||
|
float y = out.y;
|
||
|
float z = out.z;
|
||
|
float R = p_sphere[W];
|
||
|
|
||
|
// // See if mesh is close enough to use color correction.
|
||
|
// if ( ( -z - R ) < CORRECTION_CUTOFF )
|
||
|
// {
|
||
|
// gMeshUseCorrection = true;
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// gMeshUseCorrection = false;
|
||
|
// }
|
||
|
//
|
||
|
// // See if mesh is close enough to use anisotropic filtering.
|
||
|
// if ( ( -z - R ) < ANISO_CUTOFF )
|
||
|
// {
|
||
|
// gMeshUseAniso = true;
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// gMeshUseAniso = false;
|
||
|
// }
|
||
|
|
||
|
if ( R < ( z - EngineGlobals.near ) ) return false;
|
||
|
if ( R < ( EngineGlobals.far - z ) ) return false;
|
||
|
|
||
|
float sx_z = EngineGlobals.sx * z;
|
||
|
float cx_x = EngineGlobals.cx * x;
|
||
|
if ( R < ( sx_z - cx_x ) ) return false;
|
||
|
if ( R < ( sx_z + cx_x ) ) return false;
|
||
|
|
||
|
float sy_z = EngineGlobals.sy * z;
|
||
|
float cy_y = EngineGlobals.cy * y;
|
||
|
if ( R < ( sy_z - cy_y ) ) return false;
|
||
|
if ( R < ( sy_z + cy_y ) ) return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool frustum_check_sphere( Mth::Vector& p_sphere, float * p_z )
|
||
|
{
|
||
|
bool visible = true;
|
||
|
|
||
|
NsVector in;
|
||
|
NsVector out;
|
||
|
|
||
|
in.x = p_sphere[X];
|
||
|
in.y = p_sphere[Y];
|
||
|
in.z = p_sphere[Z];
|
||
|
|
||
|
EngineGlobals.local_to_camera.multiply( &in, &out );
|
||
|
|
||
|
float x = out.x;
|
||
|
float y = out.y;
|
||
|
float z = out.z;
|
||
|
float R = p_sphere[W];
|
||
|
|
||
|
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;
|
||
|
|
||
|
if ( p_z ) *p_z = out.z;
|
||
|
|
||
|
return visible;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void calculate_tex_proj_matrix( NsMatrix * p_tex_view_matrix, NsMatrix * p_tex_proj_matrix, NsMatrix * p_tex_transform_matrix, NsMatrix * p_world_matrix )
|
||
|
{
|
||
|
// Get the current view matrix.
|
||
|
NsMatrix matView, matInvView;
|
||
|
|
||
|
matView.copy( EngineGlobals.camera );
|
||
|
matInvView.invert( matView );
|
||
|
|
||
|
NsMatrix matBiasScale;
|
||
|
matBiasScale.identity();
|
||
|
|
||
|
//# ifdef TEST_SB
|
||
|
// static float x0 = 256.0f;
|
||
|
// static float y0 = 256.0f;
|
||
|
//
|
||
|
// matBiasScale._11 = x0 * 0.5f;
|
||
|
// matBiasScale._22 = y0 * -0.5f;
|
||
|
//// matBiasScale._11 = 0.5f;
|
||
|
//// matBiasScale._22 = -0.5f;
|
||
|
//// matBiasScale._33 = D3DZ_MAX_D16;
|
||
|
// matBiasScale._33 = D3DZ_MAX_D24S8;
|
||
|
//# else
|
||
|
// matBiasScale._11 = 0.5f;
|
||
|
// matBiasScale._22 = -0.5f;
|
||
|
//# endif
|
||
|
matBiasScale.setUpY( 0.5f );
|
||
|
matBiasScale.setAtZ( -0.5f );
|
||
|
|
||
|
//# ifdef TEST_SB
|
||
|
// static float x1 = 256.0f;
|
||
|
// static float y1 = 256.0f;
|
||
|
//
|
||
|
// matBiasScale._41 = x1 * 0.5f + 0.5f;
|
||
|
// matBiasScale._42 = y1 * 0.5f + 0.5f;
|
||
|
//// matBiasScale._41 = 0.5f;
|
||
|
//// matBiasScale._42 = 0.5f;
|
||
|
//# else
|
||
|
// matBiasScale._41 = 0.5f;
|
||
|
// matBiasScale._42 = 0.5f;
|
||
|
//# endif
|
||
|
matBiasScale.setPosY( 0.5f );
|
||
|
matBiasScale.setPosZ( -0.5f );
|
||
|
|
||
|
NsMatrix m_matTexProj;
|
||
|
//# if defined( TEST_SB )
|
||
|
// // Don't bother with inverse view transform for Shadow Buffer, since we are picking up world-space coordinates directly.
|
||
|
// if( p_world_matrix )
|
||
|
// {
|
||
|
// m_matTexProj = *p_world_matrix; // Transform to world space.
|
||
|
// D3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_view_matrix ); // Transform to projection camera space.
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// m_matTexProj = *p_tex_view_matrix; // Transform to projection camera space.
|
||
|
// }
|
||
|
// D3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_proj_matrix ); // Situate verts relative to projector's view
|
||
|
// D3DXMatrixMultiply( p_tex_transform_matrix, &m_matTexProj, &matBiasScale ); // Scale and bias to map the near clipping plane to texcoords
|
||
|
//# else
|
||
|
// m_matTexProj = matInvView; // Transform cameraspace position to worldspace
|
||
|
// D3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_view_matrix ); // Transform to projection camera space.
|
||
|
// D3DXMatrixMultiply( &m_matTexProj, &m_matTexProj, p_tex_proj_matrix ); // Situate verts relative to projector's view
|
||
|
// D3DXMatrixMultiply( p_tex_transform_matrix, &m_matTexProj, &matBiasScale ); // Scale and bias to map the near clipping plane to texcoords
|
||
|
//# endif
|
||
|
m_matTexProj = matInvView; // Transform cameraspace position to worldspace
|
||
|
m_matTexProj.cat( m_matTexProj, *p_tex_view_matrix );
|
||
|
m_matTexProj.cat( m_matTexProj, *p_tex_proj_matrix );
|
||
|
p_tex_transform_matrix->cat( m_matTexProj, matBiasScale );
|
||
|
|
||
|
// This is just for displaying the frustum lines.
|
||
|
/*
|
||
|
// Convert from homogeneous texmap coords to worldspace
|
||
|
D3DXMATRIX matInvTexView, matInvTexProj;
|
||
|
D3DXMatrixInverse( &matInvTexView, NULL, &matTexView );
|
||
|
D3DXMatrixInverse( &matInvTexProj, NULL, &matTexProj );
|
||
|
|
||
|
for( int i = 0; i < 8; i++ )
|
||
|
{
|
||
|
D3DXVECTOR4 vT( 0.0f, 0.0f, 0.0f, 1.0f );
|
||
|
vT.x = (i%2) * ( i&0x2 ? -1.0f : 1.0f );
|
||
|
vT.y = (i%2) * ( i&0x4 ? -1.0f : 1.0f );
|
||
|
vT.z = (i%2) * ( 1.0f );
|
||
|
|
||
|
D3DXVec4Transform( &vT, &vT, &matInvTexProj );
|
||
|
D3DXVec4Transform( &vT, &vT, &matInvTexView );
|
||
|
|
||
|
g_FrustumLines[i].x = vT.x / vT.w;
|
||
|
g_FrustumLines[i].y = vT.y / vT.w;
|
||
|
g_FrustumLines[i].z = vT.z / vT.w;
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void render_shadow_targets( void )
|
||
|
{
|
||
|
GX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
|
||
|
// D3DXMATRIX stored_view_matrix = EngineGlobals.view_matrix;
|
||
|
// D3DXMATRIX stored_projection_matrix = EngineGlobals.projection_matrix;
|
||
|
|
||
|
// Goes through the list of render target textures, rendering to each one in turn.
|
||
|
pTextureProjectionDetailsTable->IterateStart();
|
||
|
sTextureProjectionDetails *p_details = pTextureProjectionDetailsTable->IterateNext();
|
||
|
//
|
||
|
// // Set the basic pixel shader that just copies a single color (in C0) over.
|
||
|
// EngineGlobals.pixel_shader_constants[0] = 1.0f;
|
||
|
// EngineGlobals.pixel_shader_constants[1] = 1.0f;
|
||
|
// EngineGlobals.pixel_shader_constants[2] = 1.0f;
|
||
|
// EngineGlobals.pixel_shader_constants[3] = 1.0f;
|
||
|
// EngineGlobals.upload_pixel_shader_constants = true;
|
||
|
// set_pixel_shader( PixelShader3 );
|
||
|
// EngineGlobals.pixel_shader_override = PixelShader3;
|
||
|
//
|
||
|
// Clear background of shadow.
|
||
|
// NsCamera cam;
|
||
|
// cam.orthographic( 0, 0, 640, 448 );
|
||
|
// cam.begin();
|
||
|
//
|
||
|
// GX::SetZMode ( GX_FALSE, GX_ALWAYS, GX_TRUE );
|
||
|
// //NsPrim::box( 0, 0, 256, 256, (GXColor){128,128,128,255} );
|
||
|
// float zf = -( EngineGlobals.far + 0.5f );
|
||
|
// NsPrim::quad( 0, 0, zf, 640, 0, zf, 640, 448, zf, 0, 448, zf, (GXColor){128,128,128,255} );
|
||
|
// cam.end();
|
||
|
|
||
|
while( p_details )
|
||
|
{
|
||
|
if( p_details->p_model )
|
||
|
{
|
||
|
// Set the new render target.
|
||
|
/// D3DDevice_SetRenderTarget( p_details->p_texture->pD3DSurface, NULL );
|
||
|
//
|
||
|
// D3DDevice_Clear( 0, 0, D3DCLEAR_TARGET, 0, 1.0f, 0 );
|
||
|
|
||
|
// Set the view and projection transforms.
|
||
|
// EngineGlobals.view_matrix = p_details->view_matrix;
|
||
|
// EngineGlobals.projection_matrix = p_details->projection_matrix;
|
||
|
// EngineGlobals.is_orthographic = true;
|
||
|
|
||
|
// Render all instances for the CGeom's contained in this model.
|
||
|
int num_geoms = p_details->p_model->GetNumGeoms();
|
||
|
for( int i = 0; i < num_geoms; ++i )
|
||
|
{
|
||
|
Nx::CNgcGeom *p_ngc_geom = static_cast<Nx::CNgcGeom*>( p_details->p_model->GetGeomByIndex( i ));
|
||
|
CInstance *p_instance = p_ngc_geom->GetInstance();
|
||
|
|
||
|
if( p_instance->GetActive())
|
||
|
{
|
||
|
// Create the camera and attach a frame.
|
||
|
NsCamera cam;
|
||
|
//NsFrame frame;
|
||
|
//cam.setFrame( &frame );
|
||
|
|
||
|
// Assume parallel projection in this case.
|
||
|
cam.orthographic();
|
||
|
cam.orthographic( 0, 0, 256, 256 );
|
||
|
cam.setViewWindow( 128, 128 );
|
||
|
|
||
|
// Position the camera somewhere near the object, pointing directly at it.
|
||
|
float at[3];
|
||
|
float pos[3];
|
||
|
|
||
|
at[0] = p_instance->GetTransform()->GetPos()[X];
|
||
|
at[1] = p_instance->GetTransform()->GetPos()[Y];
|
||
|
at[2] = p_instance->GetTransform()->GetPos()[Z];
|
||
|
|
||
|
pos[0] = p_instance->GetTransform()->GetPos()[X];
|
||
|
pos[1] = p_instance->GetTransform()->GetPos()[Y] + 64.0f;
|
||
|
pos[2] = p_instance->GetTransform()->GetPos()[Z];
|
||
|
|
||
|
g_shadow_object_pos = p_instance->GetTransform()->GetPos();
|
||
|
g_shadow_object_pos[Y] += ( 12.0f * 3.0f ); // Amount of leeway...
|
||
|
|
||
|
// Also need to take account of the view offset.
|
||
|
Mth::Vector object_up = p_instance->GetTransform()->GetUp();
|
||
|
at[0] += object_up.GetX() * 36.0f;
|
||
|
at[1] += object_up.GetY() * 36.0f;
|
||
|
at[2] += object_up.GetZ() * 36.0f;
|
||
|
pos[0] += object_up.GetX() * 36.0f;
|
||
|
pos[1] += object_up.GetY() * 36.0f;
|
||
|
pos[2] += object_up.GetZ() * 36.0f;
|
||
|
|
||
|
cam.pos( pos[0], pos[1], pos[2] );
|
||
|
cam.up( 1.0f, 0.0f, 0.0f );
|
||
|
cam.lookAt( at[0], at[1], at[2] );
|
||
|
|
||
|
// EngineGlobals.world_to_camera.identity();
|
||
|
// EngineGlobals.world_to_camera.setPos( pos[0], pos[1], pos[2] );
|
||
|
// EngineGlobals.world_to_camera.setRight( 1.0f, 0.0f, 0.0f );
|
||
|
// EngineGlobals.world_to_camera.setUp( 0.0f, 0.0f, 1.0f );
|
||
|
// EngineGlobals.world_to_camera.setAt( 0.0f, -1.0f, 0.0f );
|
||
|
|
||
|
cam.begin();
|
||
|
MTXCopy ( (MtxPtr)cam.getCurrent(), EngineGlobals.current_uploaded );
|
||
|
|
||
|
EngineGlobals.world_to_camera.copy( *cam.getCurrent() );
|
||
|
EngineGlobals.shadow_camera.copy( *cam.getCurrent() );
|
||
|
|
||
|
// Flag the scene as having the shadow version rendered.
|
||
|
p_instance->GetScene()->m_flags |= SCENE_FLAG_RENDERING_SHADOW;
|
||
|
|
||
|
// Render the model.
|
||
|
// ROMtx bone_mtx[60];
|
||
|
// p_instance->Transform( vRENDER_SHADOW_1ST_PASS, bone_mtx, NULL );
|
||
|
// p_instance->ClearFlag( NxNgc::CInstance::INSTANCE_FLAG_TRANSFORM_ME );
|
||
|
p_instance->Render( vRENDER_SHADOW_1ST_PASS );
|
||
|
|
||
|
// Clear the flag the scene as having the shadow version rendered.
|
||
|
p_instance->GetScene()->m_flags &= ~SCENE_FLAG_RENDERING_SHADOW;
|
||
|
|
||
|
// Flag the scene as self shadowing.
|
||
|
p_instance->GetScene()->m_flags |= SCENE_FLAG_SELF_SHADOWS;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
p_details = pTextureProjectionDetailsTable->IterateNext();
|
||
|
}
|
||
|
//
|
||
|
// // Pixel shader override no longer required.
|
||
|
// EngineGlobals.pixel_shader_override = 0;
|
||
|
//
|
||
|
// // Restore the view and projection transforms.
|
||
|
// EngineGlobals.view_matrix = stored_view_matrix;
|
||
|
// EngineGlobals.projection_matrix = stored_projection_matrix;
|
||
|
// EngineGlobals.is_orthographic = false;
|
||
|
//
|
||
|
// // Restore the world transform.
|
||
|
// D3DDevice_SetTransform( D3DTS_WORLD, &EngineGlobals.world_matrix );
|
||
|
//
|
||
|
// // Restore the default render target.
|
||
|
// D3DDevice_SetRenderTarget( EngineGlobals.p_RenderSurface, EngineGlobals.p_ZStencilSurface );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void render_shadow_meshes( sScene *p_scene, int *p_mesh_indices, int num_meshes )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
void figure_wibble_vc( sScene *p_scene )
|
||
|
{
|
||
|
if ( !p_scene->mp_scene_data ) return;
|
||
|
|
||
|
// The vertex color wibble flag is placed in pass 0.
|
||
|
NxNgc::sMaterialVCWibbleKeyHeader * p_key_header = p_scene->mp_vc_wibble;
|
||
|
NxNgc::sMaterialVCWibbleKey * p_key = (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1];
|
||
|
|
||
|
int current_time = (int)Tmr::GetTime();
|
||
|
|
||
|
uint32 * p_col = p_scene->mp_col_pool;
|
||
|
|
||
|
for ( int wibble = 0; wibble < p_scene->mp_scene_data->m_num_vc_wibbles; wibble++ )
|
||
|
{
|
||
|
int num_keys = p_key_header->m_num_frames;
|
||
|
int phase_shift = p_key_header->m_phase;
|
||
|
|
||
|
// Time parameters.
|
||
|
int start_time = p_key[0].m_time;
|
||
|
int end_time = p_key[(num_keys - 1)].m_time;
|
||
|
int period = end_time - start_time;
|
||
|
int time = start_time + (( current_time + phase_shift ) % period );
|
||
|
|
||
|
// Locate the keyframe.
|
||
|
int key;
|
||
|
for( key = num_keys - 1; key >= 0; --key )
|
||
|
{
|
||
|
if( time >= p_key[key].m_time )
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Parameter expressing how far we are between between this keyframe and the next.
|
||
|
float t = (float)( time - p_key[key].m_time ) / (float)( p_key[key+1].m_time - p_key[key].m_time );
|
||
|
|
||
|
// Interpolate the color.
|
||
|
GXColor rgba;
|
||
|
rgba.r = (uint8)((( 1.0f - t ) * p_key[key].m_color.r ) + ( t * p_key[key + 1].m_color.r ));
|
||
|
rgba.g = (uint8)((( 1.0f - t ) * p_key[key].m_color.g ) + ( t * p_key[key + 1].m_color.g ));
|
||
|
rgba.b = (uint8)((( 1.0f - t ) * p_key[key].m_color.b ) + ( t * p_key[key + 1].m_color.b ));
|
||
|
rgba.a = (uint8)((( 1.0f - t ) * p_key[key].m_color.a ) + ( t * p_key[key + 1].m_color.a ));
|
||
|
|
||
|
p_col[wibble] = *((uint32*)&rgba);
|
||
|
|
||
|
// Next wibble sequence.
|
||
|
p_key_header = (NxNgc::sMaterialVCWibbleKeyHeader *)&p_key[num_keys];
|
||
|
p_key = (NxNgc::sMaterialVCWibbleKey *)&p_key_header[1];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;
|
||
|
//sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];
|
||
|
|
||
|
// Cached GX commands.
|
||
|
|
||
|
float * g_p_pos = NULL;
|
||
|
char * g_p_col0 = NULL;
|
||
|
//char * g_p_col1 = NULL;
|
||
|
GXColor g_col0 = (GXColor){0,0,0,0};
|
||
|
//GXColor g_col1 = (GXColor){0,0,0,0};
|
||
|
|
||
|
static void _reset( void )
|
||
|
{
|
||
|
g_p_pos = NULL;
|
||
|
g_p_col0 = NULL;
|
||
|
// g_p_col1 = NULL;
|
||
|
g_col0 = (GXColor){0,0,0,0};
|
||
|
// g_col1 = (GXColor){0,0,0,0};
|
||
|
GX::SetChanMatColor( GX_COLOR0A0, g_col0 );
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, g_col1 );
|
||
|
}
|
||
|
|
||
|
static void _set_pos( float * p_pos )
|
||
|
{
|
||
|
if ( g_p_pos != p_pos )
|
||
|
{
|
||
|
GX::SetArray( GX_VA_POS, p_pos, sizeof( float ) * 3 );
|
||
|
g_p_pos = p_pos;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void _set_col0( char * p_col0 )
|
||
|
{
|
||
|
if ( g_p_col0 != p_col0 )
|
||
|
{
|
||
|
GX::SetArray( GX_VA_CLR0, p_col0, sizeof( uint32 ) );
|
||
|
g_p_col0 = p_col0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//static void _set_col1( char * p_col1 )
|
||
|
//{
|
||
|
// if ( g_p_col1 != p_col1 )
|
||
|
// {
|
||
|
// GX::SetArray( GX_VA_CLR1, p_col1, sizeof( uint32 ) );
|
||
|
// g_p_col1 = p_col1;
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
static void _set_mat0( GXColor col )
|
||
|
{
|
||
|
if ( ( col.r != g_col0.r ) || ( col.g != g_col0.g ) || ( col.b != g_col0.b ) || ( col.a != g_col0.a ) )
|
||
|
{
|
||
|
g_col0 = col;
|
||
|
GX::SetChanMatColor( GX_COLOR0A0, col );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//static void _set_mat1( GXColor col )
|
||
|
//{
|
||
|
// if ( ( col.r != g_col1.r ) || ( col.g != g_col1.g ) || ( col.b != g_col1.b ) || ( col.a != g_col1.a ) )
|
||
|
// {
|
||
|
// g_col1 = col;
|
||
|
// GX::SetChanMatColor( GX_COLOR1A1, col );
|
||
|
// }
|
||
|
//}
|
||
|
|
||
|
static void submit_mesh( sScene *p_scene, sMesh * p_mesh, s16* p_posNormBuffer, Mth::Matrix * p_bone_xform, Mth::Matrix * p_instance_xform, int * p_array_base, int * p_col_base, int * p_layer, float * p_pm, GXColor * p_base_color, bool * set_base_color, bool * p_world_fog, uint32 flags )
|
||
|
{
|
||
|
// if ( g_skip_correctable && p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) ) return;
|
||
|
if ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id == g_kill_layer ) return;
|
||
|
|
||
|
if ( !p_posNormBuffer )
|
||
|
{
|
||
|
// Deal with cloned pos pools.
|
||
|
if ( p_mesh->mp_dl->mp_pos_pool )
|
||
|
{
|
||
|
_set_pos( p_mesh->mp_dl->mp_pos_pool );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Deal with verts outside of 65535.
|
||
|
_set_pos( &p_scene->mp_pos_pool[p_mesh->mp_dl->m_array_base*3] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Deal with cloned color pools.
|
||
|
if ( p_mesh->mp_dl->mp_col_pool )
|
||
|
{
|
||
|
_set_col0( &((char*)p_mesh->mp_dl->mp_col_pool)[0] );
|
||
|
// if ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )
|
||
|
// {
|
||
|
// _set_col1( &((char*)p_mesh->mp_dl->mp_col_pool)[2] );
|
||
|
// }
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Deal with resetting cloned color pools.
|
||
|
// Assumes that this isn't a skinned object.
|
||
|
_set_col0( &((char*)p_scene->mp_col_pool)[0] );
|
||
|
// if ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )
|
||
|
// {
|
||
|
// _set_col1( &((char*)p_scene->mp_col_pool)[2] );
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
// Deal with zbias.
|
||
|
if ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id != *p_layer )
|
||
|
{
|
||
|
*p_layer = p_mesh->mp_dl->m_material.p_header->m_layer_id;
|
||
|
|
||
|
float layer = p_mesh->mp_dl->m_material.p_header->m_layer_id;
|
||
|
|
||
|
float value = p_pm[6] + ( 150.0f * layer ) * p_pm[5];
|
||
|
|
||
|
GXWGFifo.u8 = GX_LOAD_XF_REG;
|
||
|
GXWGFifo.u16 = 0;
|
||
|
GXWGFifo.u16 = 0x1025;
|
||
|
GXWGFifo.f32 = value;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Billboard tweaking.
|
||
|
// enum BillboardType
|
||
|
// {
|
||
|
// BBT_NOT_BILLBOARD,
|
||
|
// BBT_SCREEN_ALIGNED,
|
||
|
// BBT_AXIAL_ALIGNED,
|
||
|
// };
|
||
|
|
||
|
// if ( p_mesh->mp_mod )
|
||
|
// {
|
||
|
// Mtx t;
|
||
|
// Mtx m;
|
||
|
//
|
||
|
//// MTXTrans( m, p_mesh->mp_mod.offset->GetX(), p_mesh->mp_mod.offset->GetY(), p_mesh->mp_mod.offset->GetZ() );
|
||
|
////
|
||
|
//// MTXRotAxisDeg(
|
||
|
//
|
||
|
// float w = p_mesh->mp_mod->offset[W];
|
||
|
// Mth::ERot90 rot = *((Mth::ERot90*)&w);
|
||
|
//
|
||
|
// if ( p_mesh->mp_mod->scale[X] > 1.0f ) OSReport( "X Scale > 1.0f: %8.3f\n", p_mesh->mp_mod->scale[X] );
|
||
|
// if ( p_mesh->mp_mod->scale[Y] > 1.0f ) OSReport( "Y Scale > 1.0f: %8.3f\n", p_mesh->mp_mod->scale[Y] );
|
||
|
// if ( p_mesh->mp_mod->scale[Z] > 1.0f ) OSReport( "Z Scale > 1.0f: %8.3f\n", p_mesh->mp_mod->scale[Z] );
|
||
|
//
|
||
|
// switch ( rot )
|
||
|
// {
|
||
|
// default:
|
||
|
// case Mth::ROT_0:
|
||
|
// MTXScaleApply( g_matrix0, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );
|
||
|
// break;
|
||
|
// case Mth::ROT_90:
|
||
|
// MTXScaleApply( g_matrix90, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );
|
||
|
// break;
|
||
|
// case Mth::ROT_180:
|
||
|
// MTXScaleApply( g_matrix180, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );
|
||
|
// break;
|
||
|
// case Mth::ROT_270:
|
||
|
// MTXScaleApply( g_matrix270, t, p_mesh->mp_mod->scale[X], p_mesh->mp_mod->scale[Y], p_mesh->mp_mod->scale[Z] );
|
||
|
// break;
|
||
|
// }
|
||
|
// t[0][3] = p_mesh->mp_mod->offset[X];
|
||
|
// t[1][3] = p_mesh->mp_mod->offset[Y];
|
||
|
// t[2][3] = p_mesh->mp_mod->offset[Z];
|
||
|
// MTXConcat( EngineGlobals.current_uploaded, t, m );
|
||
|
//
|
||
|
// GX::LoadPosMtxImm( m, GX_PNMTX0 );
|
||
|
// reload_camera = true;
|
||
|
// }
|
||
|
|
||
|
// Set Fog color if necessary.
|
||
|
bool mesh_world_fog = true;
|
||
|
if ( p_mesh->mp_dl->m_material.p_header )
|
||
|
{
|
||
|
switch ( p_mesh->mp_dl->m_material.p_header->m_base_blend )
|
||
|
{
|
||
|
case vBLEND_MODE_ADD:
|
||
|
case vBLEND_MODE_ADD_FIXED:
|
||
|
case vBLEND_MODE_SUBTRACT:
|
||
|
case vBLEND_MODE_SUB_FIXED:
|
||
|
mesh_world_fog = false;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if ( mesh_world_fog != *p_world_fog )
|
||
|
{
|
||
|
*p_world_fog = mesh_world_fog;
|
||
|
if ( mesh_world_fog )
|
||
|
{
|
||
|
Nx::CFog::sSetFogColor();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GX::SetFogColor( (GXColor){0,0,0,0} );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
MaterialSubmit( p_mesh, p_scene );
|
||
|
|
||
|
switch ( p_mesh->mp_dl->mp_object_header->m_billboard_type )
|
||
|
{
|
||
|
case 2:
|
||
|
{
|
||
|
NsMatrix* p_matrix = &EngineGlobals.world_to_camera;
|
||
|
NsVector at = *p_matrix->getAt();
|
||
|
// at.x = -at.x;
|
||
|
// at.y = -at.y;
|
||
|
// at.z = -at.z;
|
||
|
|
||
|
NsVector screen_right;
|
||
|
NsVector screen_up;
|
||
|
NsVector screen_at;
|
||
|
|
||
|
NsMatrix root;
|
||
|
|
||
|
// Create coordinate system based on camera at & pivot axis.
|
||
|
screen_up.set( p_mesh->mp_dl->mp_object_header->m_axis[X], p_mesh->mp_dl->mp_object_header->m_axis[Y], p_mesh->mp_dl->mp_object_header->m_axis[Z] );
|
||
|
// screen_right.cross( *p_matrix->getAt(), screen_up );
|
||
|
screen_right.cross( at, screen_up );
|
||
|
screen_at.cross( screen_up, screen_right );
|
||
|
|
||
|
screen_right.normalize();
|
||
|
screen_at.normalize();
|
||
|
|
||
|
root.setRightX( screen_right.x );
|
||
|
root.setRightY( screen_up.x );
|
||
|
root.setRightZ( screen_at.x );
|
||
|
|
||
|
root.setUpX( screen_right.y );
|
||
|
root.setUpY( screen_up.y );
|
||
|
root.setUpZ( screen_at.y );
|
||
|
|
||
|
root.setAtX( screen_right.z );
|
||
|
root.setAtY( screen_up.z );
|
||
|
root.setAtZ( screen_at.z );
|
||
|
|
||
|
// root.setRightX( screen_right.x );
|
||
|
// root.setRightY( screen_right.y );
|
||
|
// root.setRightZ( screen_right.z );
|
||
|
//
|
||
|
// root.setUpX( screen_up.x );
|
||
|
// root.setUpY( screen_up.y );
|
||
|
// root.setUpZ( screen_up.z );
|
||
|
//
|
||
|
// root.setAtX( screen_at.x );
|
||
|
// root.setAtY( screen_at.y );
|
||
|
// root.setAtZ( screen_at.z );
|
||
|
|
||
|
root.setPosX( p_mesh->mp_dl->mp_object_header->m_origin[X] );
|
||
|
root.setPosY( p_mesh->mp_dl->mp_object_header->m_origin[Y] );
|
||
|
root.setPosZ( p_mesh->mp_dl->mp_object_header->m_origin[Z] );
|
||
|
|
||
|
root.cat( EngineGlobals.world_to_camera, root );
|
||
|
|
||
|
GX::LoadPosMtxImm( (MtxPtr)&root, GX_PNMTX0 );
|
||
|
//GXSetCurrentMtx( GX_PNMTX1 );
|
||
|
reload_camera = true;
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
{
|
||
|
NsMatrix* p_matrix = &EngineGlobals.world_to_camera;
|
||
|
|
||
|
NsMatrix root;
|
||
|
|
||
|
// Just transpose the matrix for screen-facing.
|
||
|
root.setRightX( p_matrix->getRightX() );
|
||
|
root.setRightY( p_matrix->getUpX() );
|
||
|
root.setRightZ( p_matrix->getAtX() );
|
||
|
|
||
|
root.setUpX( p_matrix->getRightY() );
|
||
|
root.setUpY( p_matrix->getUpY() );
|
||
|
root.setUpZ( p_matrix->getAtY() );
|
||
|
|
||
|
root.setAtX( p_matrix->getRightZ() );
|
||
|
root.setAtY( p_matrix->getUpZ() );
|
||
|
root.setAtZ( p_matrix->getAtZ() );
|
||
|
|
||
|
root.setPosX( p_mesh->mp_dl->mp_object_header->m_origin[X] );
|
||
|
root.setPosY( p_mesh->mp_dl->mp_object_header->m_origin[Y] );
|
||
|
root.setPosZ( p_mesh->mp_dl->mp_object_header->m_origin[Z] );
|
||
|
|
||
|
root.cat( EngineGlobals.world_to_camera, root );
|
||
|
|
||
|
GX::LoadPosMtxImm( (MtxPtr)&root, GX_PNMTX0 );
|
||
|
//GXSetCurrentMtx( GX_PNMTX1 );
|
||
|
reload_camera = true;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
// Don't do anything - not a billboard.
|
||
|
//GXSetCurrentMtx( GX_PNMTX0 );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// // Create array of bone matrices if required.
|
||
|
// NsMatrix bone_xform[80];
|
||
|
// if ( p_scene->m_numHierarchyObjects && p_bone_xform )
|
||
|
// {
|
||
|
// for ( int bone = 0; bone < num_bones; bone++ )
|
||
|
// {
|
||
|
// Mth::Matrix temp = p_bone_xform[bone] * *p_instance_xform;
|
||
|
// NsMatrix local;
|
||
|
//
|
||
|
// local.setRightX( temp.GetRight()[X] );
|
||
|
// local.setRightY( temp.GetUp()[X] );
|
||
|
// local.setRightZ( temp.GetAt()[X] );
|
||
|
//
|
||
|
// local.setUpX( temp.GetRight()[Y] );
|
||
|
// local.setUpY( temp.GetUp()[Y] );
|
||
|
// local.setUpZ( temp.GetAt()[Y] );
|
||
|
//
|
||
|
// local.setAtX( temp.GetRight()[Z] );
|
||
|
// local.setAtY( temp.GetUp()[Z] );
|
||
|
// local.setAtZ( temp.GetAt()[Z] );
|
||
|
//
|
||
|
// local.setPosX( temp.GetPos()[X] );
|
||
|
// local.setPosY( temp.GetPos()[Y] );
|
||
|
// local.setPosZ( temp.GetPos()[Z] );
|
||
|
//
|
||
|
// bone_xform[bone].cat( EngineGlobals.world_to_camera, local );
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
|
||
|
if ( p_scene->m_numHierarchyObjects && p_bone_xform )
|
||
|
{
|
||
|
NsMatrix bone_xform;
|
||
|
Mth::Matrix temp = p_bone_xform[p_mesh->m_bone_idx] * *p_instance_xform;
|
||
|
NsMatrix local;
|
||
|
|
||
|
local.setRightX( temp.GetRight()[X] );
|
||
|
local.setRightY( temp.GetUp()[X] );
|
||
|
local.setRightZ( temp.GetAt()[X] );
|
||
|
|
||
|
local.setUpX( temp.GetRight()[Y] );
|
||
|
local.setUpY( temp.GetUp()[Y] );
|
||
|
local.setUpZ( temp.GetAt()[Y] );
|
||
|
|
||
|
local.setAtX( temp.GetRight()[Z] );
|
||
|
local.setAtY( temp.GetUp()[Z] );
|
||
|
local.setAtZ( temp.GetAt()[Z] );
|
||
|
|
||
|
local.setPosX( temp.GetPos()[X] );
|
||
|
local.setPosY( temp.GetPos()[Y] );
|
||
|
local.setPosZ( temp.GetPos()[Z] );
|
||
|
|
||
|
bone_xform.cat( EngineGlobals.world_to_camera, local );
|
||
|
|
||
|
GX::LoadPosMtxImm( (MtxPtr)&bone_xform, GX_PNMTX0 );
|
||
|
reload_camera = true;
|
||
|
|
||
|
GX::LoadNrmMtxImm((MtxPtr)&bone_xform, GX_PNMTX0);
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( /*p_scene->mp_scene_data->m_num_nrm ||*/ p_posNormBuffer || ( p_scene->m_numHierarchyObjects && p_bone_xform ) )
|
||
|
{
|
||
|
// 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 );
|
||
|
//
|
||
|
// // Set channel control for diffuse.
|
||
|
// GX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT0|GX_LIGHT1, 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 ( p_mesh->mp_dl->m_material.p_header->m_shininess > 0.0f )
|
||
|
//// {
|
||
|
//// // Set channel control for specular.
|
||
|
//// Vec ldir;
|
||
|
////
|
||
|
//// ldir.x = 0.0f; //NxNgc::EngineGlobals.light_x[0] * ( 1.0f / 200000.0f );
|
||
|
//// ldir.y = 0.0f; //NxNgc::EngineGlobals.light_y[0] * ( 1.0f / 200000.0f );
|
||
|
//// ldir.z = -1.0f; //NxNgc::EngineGlobals.light_z[0] * ( 1.0f / 200000.0f );
|
||
|
////
|
||
|
//// GX::InitSpecularDirv( &light_obj[2], &ldir );
|
||
|
//// GX::InitLightShininess( &light_obj[2], 8.0f );
|
||
|
//// GX::InitLightColor( &light_obj[2], (GXColor){255,255,255,255} );
|
||
|
//// GX::LoadLightObjImm( &light_obj[2], GX_LIGHT2 );
|
||
|
////
|
||
|
//// GX::SetChanCtrl( GX_COLOR1, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT2, GX_DF_NONE, GX_AF_SPEC );
|
||
|
//// GX::SetChanCtrl( GX_ALPHA1, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
//// }
|
||
|
//
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( !*set_base_color )
|
||
|
{
|
||
|
GX::SetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, 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 ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )
|
||
|
// {
|
||
|
// GX::SetChanCtrl( GX_COLOR1, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GX::SetChanCtrl( GX_ALPHA1, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// }
|
||
|
*set_base_color = true;
|
||
|
}
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, (GXColor){128,128,128,255} );
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, (GXColor){32,32,32,255} );
|
||
|
GXColor col;
|
||
|
col.r = p_mesh->m_base_color.r;
|
||
|
col.g = p_mesh->m_base_color.g;
|
||
|
col.b = p_mesh->m_base_color.b;
|
||
|
col.a = 255;
|
||
|
|
||
|
//// if ( !(p_mesh->mp_dl->m_material.p_header->m_flags & (1<<7)) )
|
||
|
// if ( !(flags & vRENDER_LIT) )
|
||
|
// {
|
||
|
// // Not sure why we need to force this to be set...
|
||
|
//// _set_mat0( col );
|
||
|
//// GX::SetChanMatColor( GX_COLOR0A0, col );
|
||
|
//// if ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )
|
||
|
// {
|
||
|
//// _set_mat1( col );
|
||
|
//// GX::SetChanMatColor( GX_COLOR1A1, col );
|
||
|
// }
|
||
|
//// *((uint32*)p_base_color) = *((uint32*)&col);
|
||
|
//
|
||
|
// col.r = col.r >> 1;
|
||
|
// col.g = col.g >> 1;
|
||
|
// col.b = col.b >> 1;
|
||
|
// }
|
||
|
|
||
|
// if ( *((uint32*)p_base_color) != *((uint32*)&col) )
|
||
|
{
|
||
|
// p_mesh->m_base_color.a = 255;
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, col );
|
||
|
|
||
|
_set_mat0( col );
|
||
|
// if ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<6) )
|
||
|
// {
|
||
|
//// GX::SetChanMatColor( GX_COLOR1A1, col );
|
||
|
// _set_mat1( (GXColor){col.b,col.a,0,0} );
|
||
|
// }
|
||
|
// *((uint32*)p_base_color) = *((uint32*)&col);
|
||
|
}
|
||
|
|
||
|
// GX::SetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GX::SetChanMatColor( GX_COLOR1A1, (GXColor){128,128,128,255} );
|
||
|
// GX::SetChanAmbColor( GX_COLOR1A1, (GXColor){128,128,128,255} );
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, (GXColor){64,64,64,128} );
|
||
|
// GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){64,64,64,128} );
|
||
|
}
|
||
|
|
||
|
// Major hack!!!
|
||
|
// if ( p_posNormBuffer )
|
||
|
// {
|
||
|
// unsigned char * p8 = (unsigned char *)&p_mesh->mp_dl[1];
|
||
|
// for ( uint lp = 0; lp < p_mesh->mp_dl->m_size; lp++ ) GXWGFifo.u8 = *p8++;
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
/*if ( !p_mesh->mp_dl->mp_pos_pool )*/ GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
|
||
|
if ( reload_camera )
|
||
|
{
|
||
|
GX::LoadPosMtxImm( EngineGlobals.current_uploaded, GX_PNMTX0 );
|
||
|
// GX::LoadPosMtxImm( (Mtx)current_cam.getCurrent(), GX_PNMTX0 );
|
||
|
reload_camera = false;
|
||
|
}
|
||
|
|
||
|
// // Reload color texture if necessary.
|
||
|
// if ( p_mesh->mp_dl->m_material.p_header->m_flags & (1<<5) )
|
||
|
// {
|
||
|
// // Make sure color map is uploaded.
|
||
|
// GX::UploadTexture( colorMap,
|
||
|
// 64, //COLOR_MAP_SIZE,
|
||
|
// 64, //COLOR_MAP_SIZE,
|
||
|
// GX_TF_RGBA8,
|
||
|
// GX_CLAMP,
|
||
|
// GX_CLAMP,
|
||
|
// GX_FALSE,
|
||
|
// GX_LINEAR,
|
||
|
// GX_LINEAR,
|
||
|
// 0.0f,
|
||
|
// 0.0f,
|
||
|
// 0.0f,
|
||
|
// GX_FALSE,
|
||
|
// GX_TRUE,
|
||
|
// GX_ANISO_1,
|
||
|
// GX_TEXMAP7 );
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
void render_scene( sScene *p_scene, s16* p_posNormBuffer, uint32 flags, Mth::Matrix * p_bone_xform, Mth::Matrix * p_instance_xform, int num_bones )
|
||
|
{
|
||
|
// Don't render dictionary scenes.
|
||
|
if( p_scene->m_is_dictionary )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// // This forces the texture to go into the unusable region.
|
||
|
// GX::UploadTexture( colorMap,
|
||
|
// 64,
|
||
|
// 64,
|
||
|
// GX_TF_RGBA8,
|
||
|
// GX_CLAMP,
|
||
|
// GX_CLAMP,
|
||
|
// GX_FALSE,
|
||
|
// GX_LINEAR,
|
||
|
// GX_LINEAR,
|
||
|
// 0.0f,
|
||
|
// 0.0f,
|
||
|
// 0.0f,
|
||
|
// GX_FALSE,
|
||
|
// GX_TRUE,
|
||
|
// GX_ANISO_1,
|
||
|
// GX_TEXMAP7 );
|
||
|
|
||
|
sLastUV = NULL;
|
||
|
|
||
|
first_mat = true;
|
||
|
|
||
|
p_last_material = NULL;
|
||
|
last_correct = false;
|
||
|
// if ( p_scene->m_numHierarchyObjects == 0 )
|
||
|
// {
|
||
|
// // Not hierarchical, set to matrix 0.
|
||
|
// GXSetCurrentMtx( GX_PNMTX0 );
|
||
|
// }
|
||
|
|
||
|
ResetMaterialChange();
|
||
|
// int meshes_rendered = 0;
|
||
|
|
||
|
figure_wibble_vc( p_scene );
|
||
|
|
||
|
#define MAX_SHADOW_MESHES 512
|
||
|
|
||
|
// int shadow_meshes = 0;
|
||
|
// sMesh *pShadow[MAX_SHADOW_MESHES];
|
||
|
|
||
|
// sMesh *visible_mesh_array[2000];
|
||
|
// int visible_mesh_array_index = 0;
|
||
|
|
||
|
// Increment the scene framestamp.
|
||
|
//_scene->m_framestamp++;
|
||
|
|
||
|
// Set up the texture generation matrix here.
|
||
|
// Mtx light;
|
||
|
// MTXLightOrtho( light, -128.0f, 128.0f, -128.0f, 128.0f, 0.5f, 0.5f, 0.5f, 0.5f );
|
||
|
// MTXConcat( light, (Mtx)&EngineGlobals.shadow_camera, light );
|
||
|
//#ifndef SHORT_VERT
|
||
|
// GX::LoadTexMtxImm( light, GX_TEXMTX7, GX_MTX3x4 );
|
||
|
//#endif // SHORT_VERT
|
||
|
|
||
|
if ( p_posNormBuffer )
|
||
|
{
|
||
|
GX::SetArray( GX_VA_POS, p_posNormBuffer, sizeof( uint16 ) * 6 );
|
||
|
GX::SetArray( GX_VA_NRM, &p_posNormBuffer[3], sizeof( uint16 ) * 6 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
GX::SetArray( GX_VA_POS, p_scene->mp_pos_pool, sizeof( float ) * 3 );
|
||
|
GX::SetArray( GX_VA_NRM, p_scene->mp_nrm_pool, sizeof( uint16 ) * 3 );
|
||
|
}
|
||
|
int array_base = 0;
|
||
|
int col_base = 2;
|
||
|
int layer = -1;
|
||
|
bool set_chan = false;
|
||
|
GXColor base_color = { 0, 0, 0, 0 };
|
||
|
bool world_fog = true;
|
||
|
Nx::CFog::sSetFogColor();
|
||
|
GX::SetChanMatColor( GX_COLOR0A0, base_color );
|
||
|
GX::SetChanMatColor( GX_COLOR1A1, base_color );
|
||
|
f32 pm[GX_PROJECTION_SZ];
|
||
|
GX::GetProjectionv( pm );
|
||
|
|
||
|
|
||
|
// if ( flags & vRENDER_NEW_TEST )
|
||
|
{
|
||
|
// Pool setup.
|
||
|
GX::SetArray( GX_VA_CLR0, &((char*)p_scene->mp_col_pool)[0], sizeof( uint32 ) );
|
||
|
GX::SetArray( GX_VA_CLR1, &((char*)p_scene->mp_col_pool)[2], sizeof( uint32 ) );
|
||
|
|
||
|
// GX::SetArray( GX_VA_CLR1, p_scene->mp_col_pool, sizeof( uint32 ) );
|
||
|
// GX::SetArray( GX_VA_TEX0, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
//
|
||
|
// GX::SetArray( GX_VA_TEX1, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
// GX::SetArray( GX_VA_TEX2, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
// GX::SetArray( GX_VA_TEX3, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
|
||
|
GX::SetArray( GX_VA_TEX0, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );
|
||
|
GX::SetArray( GX_VA_TEX1, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );
|
||
|
GX::SetArray( GX_VA_TEX2, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );
|
||
|
GX::SetArray( GX_VA_TEX3, p_scene->mp_tex_pool, sizeof( uint16 ) * 2 );
|
||
|
|
||
|
// GXSetArray( GX_VA_TEX4, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
// GXSetArray( GX_VA_TEX5, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
// GXSetArray( GX_VA_TEX6, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
// GXSetArray( GX_VA_TEX7, p_scene->mp_tex_pool, sizeof( float ) * 2 );
|
||
|
//GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if ( g_object == g_view_object ) g_view_scene = p_scene;
|
||
|
|
||
|
// Render all meshes.
|
||
|
# ifdef __USE_PROFILER__
|
||
|
Sys::VUProfiler->PushContext( 128,0,0 );
|
||
|
# endif // __USE_PROFILER__
|
||
|
|
||
|
// {
|
||
|
// GX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );
|
||
|
// GX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
|
||
|
//
|
||
|
// GX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST,
|
||
|
// GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
//
|
||
|
// GX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST,
|
||
|
// GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
|
||
|
// GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
//
|
||
|
// GX::SetBlendMode ( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
//
|
||
|
// GX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );
|
||
|
// GX::SetTevKColor( GX_KCOLOR0, (GXColor){8,8,8,255} );
|
||
|
// GX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255});
|
||
|
// GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255});
|
||
|
//
|
||
|
// GX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
|
||
|
// GX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );
|
||
|
// }
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Shadow Target.
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
if ( flags & vRENDER_SHADOW_1ST_PASS )
|
||
|
{
|
||
|
// GX::SetFog( GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, (GXColor){0,0,0,0} );
|
||
|
GX::SetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
|
||
|
|
||
|
GX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_KONST,
|
||
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
|
||
|
GX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST,
|
||
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
|
||
|
GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
|
||
|
GX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE ); // Replace
|
||
|
|
||
|
GX::SetTevKSel( GX_TEVSTAGE0, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A, GX_TEV_KCSEL_K0, GX_TEV_KASEL_K0_A );
|
||
|
GX::SetTevKColor( GX_KCOLOR0, (GXColor){64,64,64,255} );
|
||
|
GX::SetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
GX::SetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255});
|
||
|
GX::SetChanAmbColor( GX_COLOR0A0, (GXColor){255,255,255,255});
|
||
|
GX::SetChanMatColor( GX_COLOR1A1, (GXColor){255,255,255,255});
|
||
|
GX::SetChanAmbColor( GX_COLOR1A1, (GXColor){255,255,255,255});
|
||
|
base_color = (GXColor){ 255, 255, 255, 255 };
|
||
|
|
||
|
// GX::SetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
|
||
|
GX::SetTexChanTevIndCull( 0, 1, 1, 0, GX_CULL_NONE );
|
||
|
|
||
|
for ( int mesh = 0; mesh < p_scene->m_num_filled_meshes; mesh++ )
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )
|
||
|
{
|
||
|
GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
|
||
|
|
||
|
// submit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &world_fog, flags );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Opaque meshes.
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
_reset();
|
||
|
if ( flags & vRENDER_OPAQUE )
|
||
|
{
|
||
|
// GX::SetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );
|
||
|
for ( int mesh = 0; mesh < p_scene->m_num_opaque_meshes; mesh++ )
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )
|
||
|
{
|
||
|
submit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Semitransparent meshes.
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
if ( flags & vRENDER_SEMITRANSPARENT )
|
||
|
{
|
||
|
// GX::SetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );
|
||
|
int opaque = p_scene->m_num_opaque_meshes;
|
||
|
int presemi = opaque + p_scene->m_num_pre_semitrans_meshes;
|
||
|
int dynsemi = presemi + p_scene->m_num_dynamic_semitrans_meshes;
|
||
|
int postsemi = dynsemi + p_scene->m_num_post_semitrans_meshes;
|
||
|
|
||
|
// Pre meshes.
|
||
|
_reset();
|
||
|
for ( int mesh = opaque; mesh < presemi; mesh++ )
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )
|
||
|
{
|
||
|
submit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Dynamic meshes.
|
||
|
sSortedMeshEntry sortedMeshArray[1000];
|
||
|
int next_sorted_mesh_entry = 0;
|
||
|
|
||
|
for ( int mesh = presemi; mesh < dynsemi; mesh++ )
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )
|
||
|
{
|
||
|
sortedMeshArray[next_sorted_mesh_entry].p_mesh = p_mesh;
|
||
|
sortedMeshArray[next_sorted_mesh_entry].sort = frustum_sort_mid( p_mesh->mp_dl->m_sphere );
|
||
|
++next_sorted_mesh_entry;
|
||
|
}
|
||
|
}
|
||
|
qsort( sortedMeshArray, next_sorted_mesh_entry, sizeof( sSortedMeshEntry ), cmp );
|
||
|
|
||
|
_reset();
|
||
|
for( int m = 0; m < next_sorted_mesh_entry; ++m )
|
||
|
{
|
||
|
submit_mesh( p_scene, sortedMeshArray[m].p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );
|
||
|
}
|
||
|
|
||
|
// Post meshes.
|
||
|
_reset();
|
||
|
for ( int mesh = dynsemi; mesh < postsemi; mesh++ )
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
( ( g_object != g_view_object ) || ( &p_scene->mp_material_header[g_material] != p_mesh->mp_dl->m_material.p_header ) ) )
|
||
|
{
|
||
|
submit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &base_color, &set_chan, &world_fog, flags );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Shadow Mesh.
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
if ( flags & vRENDER_SHADOW_2ND_PASS )
|
||
|
{
|
||
|
Nx::CFog::sEnableFog( false );
|
||
|
Mtx light;
|
||
|
MTXLightOrtho( light, -128.0f, 128.0f, -128.0f, 128.0f, 0.5f, 0.5f, 0.5f, 0.5f );
|
||
|
MTXConcat( light, (Mtx)&EngineGlobals.shadow_camera, light );
|
||
|
GX::LoadTexMtxImm( light, GX_TEXMTX7, GX_MTX3x4 );
|
||
|
GX::SetZMode( GX_TRUE, GX_LEQUAL, GX_FALSE );
|
||
|
|
||
|
GX::SetZCompLoc( GX_TRUE );
|
||
|
GX::UploadTexture( shadowTextureData,
|
||
|
SHADOW_TEXTURE_SIZE,
|
||
|
SHADOW_TEXTURE_SIZE,
|
||
|
GX_TF_I4,
|
||
|
GX_CLAMP,
|
||
|
GX_CLAMP,
|
||
|
GX_FALSE,
|
||
|
GX_LINEAR,
|
||
|
GX_LINEAR,
|
||
|
0.0f,
|
||
|
0.0f,
|
||
|
0.0f,
|
||
|
GX_FALSE,
|
||
|
GX_TRUE,
|
||
|
GX_ANISO_1,
|
||
|
GX_TEXMAP0 );
|
||
|
GX::SetTexCoordScale( GX_TEXCOORD0, GX_TRUE, SHADOW_TEXTURE_SIZE, SHADOW_TEXTURE_SIZE );
|
||
|
|
||
|
GX::UploadPalette( shadowPalette,
|
||
|
GX_TL_RGB5A3,
|
||
|
GX_TLUT_16,
|
||
|
GX_TEXMAP0 );
|
||
|
|
||
|
GX::SetTexChanTevIndCull( 1, 0, 1, 0, GX_CULL_NONE );
|
||
|
GX::SetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_FALSE, GX_PTIDENTITY );
|
||
|
|
||
|
GX::SetCurrMtxPosTex03( GX_PNMTX0, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY, GX_IDENTITY );
|
||
|
|
||
|
GX::SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0 );
|
||
|
// GX::SetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE ); // Replace
|
||
|
GX::SetBlendMode( GX_BM_BLEND, GX_BL_DSTCLR, GX_BL_ZERO, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_TRUE );
|
||
|
GX::SetCurrMtxPosTex03( GX_PNMTX0, GX_TEXMTX7, GX_TEXMTX7, GX_TEXMTX7, GX_TEXMTX7 );
|
||
|
|
||
|
GX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL);
|
||
|
GX::SetTevAlphaInOpSwap( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO,
|
||
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,
|
||
|
GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
GX::SetTevColorInOp( GX_TEVSTAGE0, GX_CC_ONE, GX_CC_ZERO, GX_CC_TEXC, GX_CC_ZERO,
|
||
|
GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );
|
||
|
|
||
|
|
||
|
//out_reg = (d (op) ((1.0 - c)*a + c*b) + bias) * scale;
|
||
|
|
||
|
GX::SetVtxDesc( 2, GX_VA_POS, GX_DIRECT, GX_VA_TEX0, GX_DIRECT );
|
||
|
|
||
|
// visible_mesh_array[visible_mesh_array_index++] = p_scene->m_semitransparent_meshes[e];
|
||
|
// for ( int mesh = 0; mesh < p_scene->m_num_filled_meshes; mesh++ )
|
||
|
|
||
|
layer = 5; // Force subsequent materials to reset the layer.
|
||
|
|
||
|
// float value = pm[6] + ( 80.0f * p_mesh->mp_dl->m_material.p_header->m_layer_id ) * pm[5];
|
||
|
float value = pm[6] + ( 150.0f * 5 ) * pm[5];
|
||
|
|
||
|
GXWGFifo.u8 = GX_LOAD_XF_REG;
|
||
|
GXWGFifo.u16 = 0;
|
||
|
GXWGFifo.u16 = 0x1025;
|
||
|
GXWGFifo.f32 = value;
|
||
|
|
||
|
// for ( int mesh = 0; mesh < ( p_scene->m_num_opaque_meshes + p_scene->m_num_pre_semitrans_meshes ); mesh++ )
|
||
|
for ( int mesh = 0; mesh < ( p_scene->m_num_filled_meshes ); mesh++ )
|
||
|
|
||
|
{
|
||
|
sMesh * p_mesh = p_scene->mpp_mesh_list[mesh];
|
||
|
|
||
|
// if( frustum_check_sphere( light, p_scene->m_opaque_meshes[e]->m_sphere ))
|
||
|
float by;
|
||
|
|
||
|
// if ( p_mesh->mp_mod )
|
||
|
// {
|
||
|
//// by = ( p_mesh->m_bottom_y * p_mesh->mp_mod->scale[Y] ) + p_mesh->mp_mod->offset[Y];
|
||
|
// by = p_mesh->mp_mod->offset[Y];
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
by = p_mesh->m_bottom_y;
|
||
|
// }
|
||
|
|
||
|
if ( ( p_mesh->m_flags & sMesh::MESH_FLAG_VISIBLE ) &&
|
||
|
frustum_check_sphere( light, p_mesh->mp_dl->m_sphere ) &&
|
||
|
( g_shadow_object_pos[Y] > by ) &&
|
||
|
!( p_mesh->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ) )
|
||
|
{
|
||
|
|
||
|
// if ( (int)p_mesh->mp_dl->m_material.p_header->m_layer_id == g_kill_layer ) return;
|
||
|
|
||
|
// Deal with cloned pos pools.
|
||
|
if ( p_mesh->mp_dl->mp_pos_pool )
|
||
|
{
|
||
|
array_base = -1;
|
||
|
GX::SetArray( GX_VA_POS, p_mesh->mp_dl->mp_pos_pool, sizeof( float ) * 3 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Deal with verts outside of 65535.
|
||
|
if ( p_mesh->mp_dl->m_array_base != (uint32)array_base )
|
||
|
{
|
||
|
array_base = p_mesh->mp_dl->m_array_base;
|
||
|
|
||
|
// Assumes that this isn't a skinned object.
|
||
|
GX::SetArray( GX_VA_POS, &p_scene->mp_pos_pool[p_mesh->mp_dl->m_array_base*3], sizeof( float ) * 3 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
|
||
|
|
||
|
// submit_mesh( p_scene, p_mesh, p_posNormBuffer, p_bone_xform, p_instance_xform, &array_base, &col_base, &layer, pm, &world_fog, flags );
|
||
|
}
|
||
|
}
|
||
|
Nx::CFog::sEnableFog( true );
|
||
|
world_fog = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// // Render opaque meshes.
|
||
|
// if( (flags & vRENDER_OPAQUE) && !(flags & vRENDER_SHADOW_1ST_PASS) )
|
||
|
// {
|
||
|
// for( int e = 0; e < p_scene->m_num_opaque_entries; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_opaque_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// sMesh * p_mesh = p_scene->m_opaque_meshes[e];
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// if ( flags & vRENDER_NEW_TEST )
|
||
|
// {
|
||
|
// // Textured.
|
||
|
// // First pass material setup.
|
||
|
// sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;
|
||
|
// sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];
|
||
|
//
|
||
|
// if ( p_pass[0].m_texture.p_data )
|
||
|
// {
|
||
|
// if ( first_mat || !one_mat )
|
||
|
// {
|
||
|
// first_mat = false;
|
||
|
//
|
||
|
// MaterialSubmit( p_mesh );
|
||
|
// }
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// // Untextured.
|
||
|
// if ( !(p_mesh->mp_dl->m_flags & 0x00200000) )
|
||
|
// {
|
||
|
// GXSetNumTevStages( 1 );
|
||
|
// GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
||
|
// GXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
// GXSetNumTexGens( 0 );
|
||
|
// GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
//// GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );
|
||
|
// GXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );
|
||
|
// GXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );
|
||
|
// GXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );
|
||
|
// GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GXSetChanMatColor( GX_COLOR0A0, (GXColor){255,255,255,255} );
|
||
|
//// GXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// multi_mesh( p_mesh, p_posNormBuffer );
|
||
|
// }
|
||
|
//
|
||
|
// // Now draw the opaque meshes with shadow mapped on them.
|
||
|
// if( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )
|
||
|
// {
|
||
|
// if( !( p_mesh->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ) )
|
||
|
// {
|
||
|
// if( frustum_check_sphere( light, p_scene->m_opaque_meshes[e]->m_sphere ))
|
||
|
// {
|
||
|
// //if( frustum_check_box( light, p_scene->m_opaque_meshes[e]->m_bbox ))
|
||
|
// {
|
||
|
// if ( shadow_meshes < MAX_SHADOW_MESHES )
|
||
|
// {
|
||
|
// pShadow[shadow_meshes] = p_mesh;
|
||
|
// shadow_meshes++;
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
//// Render semi-transparent meshes.
|
||
|
// if( (flags & vRENDER_SEMITRANSPARENT) && !(flags & vRENDER_SHADOW_1ST_PASS) )
|
||
|
// {
|
||
|
// int e = 0;
|
||
|
// int next_sorted_mesh_entry = 0;
|
||
|
//
|
||
|
// // Semitransparent rendering is done in three stages.
|
||
|
// // The first stage is meshes in the list up to the point where dynamic sorting starts.
|
||
|
// // The second stage is meshes in the list which use dynamic sorting.
|
||
|
// // The third stage is meshes in the list beyond the point where dynamic sorting ends.
|
||
|
// for( ; e < p_scene->m_first_dynamic_sort_entry; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// sMesh * p_mesh = p_scene->m_semitransparent_meshes[e];
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// ++meshes_rendered;
|
||
|
//
|
||
|
// if ( flags & vRENDER_NEW_TEST )
|
||
|
// {
|
||
|
// // Textured.
|
||
|
// // First pass material setup.
|
||
|
// sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;
|
||
|
// sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];
|
||
|
//
|
||
|
// if ( p_pass[0].m_texture.p_data )
|
||
|
// {
|
||
|
// if ( first_mat || !one_mat )
|
||
|
// {
|
||
|
// first_mat = false;
|
||
|
//
|
||
|
// MaterialSubmit( p_mesh );
|
||
|
// }
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// // Untextured.
|
||
|
// if ( !(p_mesh->mp_dl->m_flags & 0x00200000) )
|
||
|
// {
|
||
|
// GXSetNumTevStages( 1 );
|
||
|
// GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
||
|
// GXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
// GXSetNumTexGens( 0 );
|
||
|
// GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );
|
||
|
// GXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );
|
||
|
// GXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );
|
||
|
// GXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );
|
||
|
// GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// multi_mesh( p_mesh, p_posNormBuffer );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// if( p_scene->m_num_dynamic_sort_entries > 0 )
|
||
|
// {
|
||
|
// // Second stage - dynamically sorted meshes.
|
||
|
// int last_dynamic_sort_entry = p_scene->m_first_dynamic_sort_entry + p_scene->m_num_dynamic_sort_entries;
|
||
|
// for( ; e < last_dynamic_sort_entry; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// ++meshes_rendered;
|
||
|
// // Figure the midpoint of this mesh, and sort it into the render list.
|
||
|
// float midpoint = frustum_sort_mid( p_scene->m_semitransparent_meshes[e]->m_sphere );
|
||
|
//
|
||
|
//// // Add this mesh to the visible list.
|
||
|
//// if( !( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_NO_SKATER_SHADOW ))
|
||
|
//// {
|
||
|
//// visible_mesh_array[visible_mesh_array_index++] = p_scene->m_semitransparent_meshes[e];
|
||
|
//// }
|
||
|
//
|
||
|
// sortedMeshArray[next_sorted_mesh_entry].p_mesh = p_scene->m_semitransparent_meshes[e];
|
||
|
// sortedMeshArray[next_sorted_mesh_entry].sort = midpoint;
|
||
|
// ++next_sorted_mesh_entry;
|
||
|
// }
|
||
|
// }
|
||
|
// if( next_sorted_mesh_entry > 0 )
|
||
|
// {
|
||
|
// // Sort the array into ascending sort order.
|
||
|
// qsort( sortedMeshArray, next_sorted_mesh_entry, sizeof( sSortedMeshEntry ), cmp );
|
||
|
//
|
||
|
// for( int m = 0; m < next_sorted_mesh_entry; ++m )
|
||
|
// {
|
||
|
// sMesh * p_mesh = sortedMeshArray[m].p_mesh;
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// if ( flags & vRENDER_NEW_TEST )
|
||
|
// {
|
||
|
// // Textured.
|
||
|
// // First pass material setup.
|
||
|
// sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;
|
||
|
// sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];
|
||
|
//
|
||
|
// if ( p_pass[0].m_texture.p_data )
|
||
|
// {
|
||
|
// if ( first_mat || !one_mat )
|
||
|
// {
|
||
|
// first_mat = false;
|
||
|
//
|
||
|
// MaterialSubmit( p_mesh );
|
||
|
// }
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// // Untextured.
|
||
|
// if ( !(p_mesh->mp_dl->m_flags & 0x00200000) )
|
||
|
// {
|
||
|
// GXSetNumTevStages( 1 );
|
||
|
// GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
||
|
// GXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
// GXSetNumTexGens( 0 );
|
||
|
// GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );
|
||
|
// GXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );
|
||
|
// GXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );
|
||
|
// GXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );
|
||
|
// GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// multi_mesh( p_mesh, p_posNormBuffer );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// // Third stage - meshes after the dynamically sorted set.
|
||
|
// for( ; e < p_scene->m_num_semitransparent_entries; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// sMesh * p_mesh = p_scene->m_semitransparent_meshes[e];
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// ++meshes_rendered;
|
||
|
//
|
||
|
// if ( flags & vRENDER_NEW_TEST )
|
||
|
// {
|
||
|
// // Textured.
|
||
|
// // First pass material setup.
|
||
|
// sMaterialHeader * p_mat = p_mesh->mp_dl->m_material.p_header;
|
||
|
// sMaterialPassHeader * p_pass = (sMaterialPassHeader *)&p_mat[1];
|
||
|
//
|
||
|
// if ( p_pass[0].m_texture.p_data )
|
||
|
// {
|
||
|
// if ( first_mat || !one_mat )
|
||
|
// {
|
||
|
// first_mat = false;
|
||
|
//
|
||
|
// MaterialSubmit( p_mesh );
|
||
|
// }
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// // Untextured.
|
||
|
// if ( !(p_mesh->mp_dl->m_flags & 0x00200000) )
|
||
|
// {
|
||
|
// GXSetNumTevStages( 1 );
|
||
|
// GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
||
|
// GXSetTevSwapMode( GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0 );
|
||
|
// GXSetNumTexGens( 0 );
|
||
|
// GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_2, GX_ENABLE, GX_TEVPREV );
|
||
|
// GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0 );
|
||
|
// GXSetBlendMode ( GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR, GX_TRUE, GX_FALSE, GX_FALSE );
|
||
|
// GXSetTevAlphaIn ( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA );
|
||
|
// GXSetTevColorIn ( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC );
|
||
|
// GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_VTX, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
|
||
|
// GXSetChanMatColor( GX_COLOR0A0, p_pass->m_color );
|
||
|
//
|
||
|
// GX::CallDisplayList ( &p_mesh->mp_dl[1], p_mesh->mp_dl->m_size );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// else
|
||
|
// {
|
||
|
// multi_mesh( p_mesh, p_posNormBuffer );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
//// // Now draw the semitransparent meshes with shadow mapped on them.
|
||
|
//// if( p_scene->m_flags & SCENE_FLAG_RECEIVE_SHADOWS )
|
||
|
//// {
|
||
|
//// render_shadow_meshes( p_scene, visible_mesh_array, visible_mesh_array_index );
|
||
|
//// }
|
||
|
// }
|
||
|
//
|
||
|
//// if ( 0 )
|
||
|
// {
|
||
|
// // Render shadow meshes.
|
||
|
// if( flags & vRENDER_SHADOW_1ST_PASS )
|
||
|
// {
|
||
|
// int e;
|
||
|
// for( e = 0; e < p_scene->m_num_opaque_entries; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_opaque_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// sMesh * p_mesh = p_scene->m_opaque_meshes[e];
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// if ( p_posNormBuffer ) {
|
||
|
// // Skinned.
|
||
|
// multi_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );
|
||
|
// } else {
|
||
|
// // Not skinned.
|
||
|
//#ifdef SHORT_VERT
|
||
|
// cam_offset( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );
|
||
|
// multi_start_16 ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );
|
||
|
//#else
|
||
|
// multi_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );
|
||
|
//#endif // SHORT_VERT
|
||
|
// }
|
||
|
//
|
||
|
// multi_end( p_mesh, vRENDER_SHADOW_1ST_PASS );
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// for( e = 0; e < p_scene->m_num_semitransparent_entries; ++e )
|
||
|
// {
|
||
|
// if ( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_VISIBLE )
|
||
|
// {
|
||
|
// sMesh * p_mesh = p_scene->m_semitransparent_meshes[e];
|
||
|
//
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
//
|
||
|
// if ( p_posNormBuffer ) {
|
||
|
// // Skinned.
|
||
|
// multi_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );
|
||
|
// } else {
|
||
|
// // Not skinned.
|
||
|
//#ifdef SHORT_VERT
|
||
|
// cam_offset( p_mesh->m_offset_x, p_mesh->m_offset_y, p_mesh->m_offset_z );
|
||
|
// multi_start_16 ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );
|
||
|
//#else
|
||
|
// multi_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );
|
||
|
//#endif // SHORT_VERT
|
||
|
// }
|
||
|
//
|
||
|
// multi_end( p_mesh, vRENDER_SHADOW_1ST_PASS );
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// // Render shadows from list.
|
||
|
//#if 1
|
||
|
// for ( int lp = 0; lp < shadow_meshes; lp++ )
|
||
|
// {
|
||
|
// GXTlutObj palObj;
|
||
|
// GXInitTlutObj( &palObj, &shadowPalette, GX_TL_RGB5A3, 16 );
|
||
|
// GXLoadTlut ( &palObj, GX_TLUT0 );
|
||
|
//
|
||
|
// // Set up shadow map texture
|
||
|
//#define SHADOW_TEXTURE_SIZE 256
|
||
|
//#define BLUR_TEXTURE_SIZE 64
|
||
|
// GXTexObj blurTexture;
|
||
|
// GXTexObj shadowTexture;
|
||
|
// GXInitTexObjCI(
|
||
|
// &blurTexture,
|
||
|
// blurTextureData, //shadowTextureData,
|
||
|
// BLUR_TEXTURE_SIZE, //SHADOW_TEXTURE_SIZE,
|
||
|
// BLUR_TEXTURE_SIZE, //SHADOW_TEXTURE_SIZE,
|
||
|
// GX_TF_C4,
|
||
|
// GX_CLAMP,
|
||
|
// GX_CLAMP,
|
||
|
// GX_FALSE,
|
||
|
// GX_TLUT0 );
|
||
|
//// GXInitTexObjLOD(&blurTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
|
||
|
// GXLoadTexObj( &blurTexture, GX_TEXMAP5 );
|
||
|
// GXInitTexObjCI(
|
||
|
// &shadowTexture,
|
||
|
// shadowTextureData,
|
||
|
// SHADOW_TEXTURE_SIZE,
|
||
|
// SHADOW_TEXTURE_SIZE,
|
||
|
// GX_TF_C4,
|
||
|
// GX_CLAMP,
|
||
|
// GX_CLAMP,
|
||
|
// GX_FALSE,
|
||
|
// GX_TLUT0 );
|
||
|
//// GXInitTexObjLOD(&shadowTexture, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
|
||
|
// GXLoadTexObj( &shadowTexture, GX_TEXMAP6 );
|
||
|
//
|
||
|
// // Offset the texture matrix.
|
||
|
//#ifdef SHORT_VERT
|
||
|
// Mtx m;
|
||
|
// MTXTrans( m, pShadow[lp]->m_offset_x, pShadow[lp]->m_offset_y, pShadow[lp]->m_offset_z );
|
||
|
// MTXConcat( light, m, m );
|
||
|
// GXLoadTexMtxImm( m, GX_TEXMTX7, GX_MTX3x4 );
|
||
|
//#endif // SHORT_VERT
|
||
|
//
|
||
|
// if ( p_posNormBuffer ) {
|
||
|
// // Skinned.
|
||
|
// multi_start_16 ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );
|
||
|
// } else {
|
||
|
// // Not skinned.
|
||
|
//#ifdef SHORT_VERT
|
||
|
// cam_offset( pShadow[lp]->m_offset_x, pShadow[lp]->m_offset_y, pShadow[lp]->m_offset_z );
|
||
|
// multi_start_16 ( pShadow[lp]->mp_posBuffer, pShadow[lp]->mp_normBuffer, 3, 3 );
|
||
|
//#else
|
||
|
// multi_start ( pShadow[lp]->mp_posBuffer, pShadow[lp]->mp_normBuffer, 3, 3 );
|
||
|
//#endif // SHORT_VERT
|
||
|
// }
|
||
|
//
|
||
|
// multi_end( pShadow[lp], vRENDER_SHADOW_2ND_PASS );
|
||
|
// }
|
||
|
//#endif
|
||
|
// }
|
||
|
//
|
||
|
//// if( flags & vRENDER_SEMITRANSPARENT )
|
||
|
//// {
|
||
|
//// // Sort semi-transparent meshes.
|
||
|
//// int bucket_size = p_scene->m_num_semitransparent_entries * 2;
|
||
|
//// sMesh * sorted_meshes[bucket_size];
|
||
|
//// memset( sorted_meshes, 0, bucket_size * 4 );
|
||
|
//// for( int e = 0; e < p_scene->m_num_semitransparent_entries; ++e )
|
||
|
//// {
|
||
|
//// if( p_scene->m_semitransparent_meshes[e]->m_flags & sMesh::MESH_FLAG_ACTIVE )
|
||
|
//// {
|
||
|
//// // Frustum cull this set of meshes, using the associated bounding box.
|
||
|
//// float z;
|
||
|
//// if( frustum_check_sphere( p_scene->m_semitransparent_meshes[e]->m_sphere, &z ))
|
||
|
//// {
|
||
|
//// int index = (int)( z / ( 20000.0f / bucket_size ) );
|
||
|
//// if ( index < 0 ) index = 0;
|
||
|
//// if ( index > (bucket_size - 1) ) index = (bucket_size - 1);
|
||
|
////
|
||
|
//// if ( index >= (bucket_size / 2) )
|
||
|
//// {
|
||
|
//// // Search backwards to find an empty slot.
|
||
|
//// while ( sorted_meshes[index] ) index--;
|
||
|
//// if ( index >= 0 )
|
||
|
//// {
|
||
|
//// sorted_meshes[index] = p_scene->m_semitransparent_meshes[e];
|
||
|
//// }
|
||
|
//// }
|
||
|
//// else
|
||
|
//// {
|
||
|
//// // Search forwards to find an empty slot.
|
||
|
//// while ( sorted_meshes[index] ) index++;
|
||
|
//// if ( index < bucket_size )
|
||
|
//// {
|
||
|
//// sorted_meshes[index] = p_scene->m_semitransparent_meshes[e];
|
||
|
//// }
|
||
|
//// }
|
||
|
//// }
|
||
|
//// }
|
||
|
//// }
|
||
|
////
|
||
|
//// // Render semi-transparent meshes.
|
||
|
//// for( int e = 0; e < bucket_size; ++e )
|
||
|
//// {
|
||
|
//// if( sorted_meshes[e] )
|
||
|
//// {
|
||
|
//// ++meshes_rendered;
|
||
|
////
|
||
|
//// sMesh * p_mesh = sorted_meshes[e];
|
||
|
////
|
||
|
//// set_render_state( RS_ZWRITEENABLE, p_mesh->m_zwrite );
|
||
|
////
|
||
|
////// if ( p_mesh->mp_uvBuffer && p_mesh->mp_material->pTex[0] )
|
||
|
//// {
|
||
|
//// uint32 layer;
|
||
|
////
|
||
|
//// if ( p_posNormBuffer ) {
|
||
|
//// // Skinned.
|
||
|
//// multi_start ( &p_posNormBuffer[0], &p_posNormBuffer[3], 6, 6 );
|
||
|
//// } else {
|
||
|
//// // Not skinned.
|
||
|
//// multi_start ( p_mesh->mp_posBuffer, p_mesh->mp_normBuffer, 3, 3 );
|
||
|
//// }
|
||
|
//// multi_add_color ( p_mesh->mp_colBuffer );
|
||
|
//// int uv_set = 0;
|
||
|
//// float * p_tex;
|
||
|
//// for ( layer = 0; layer < p_mesh->mp_material->Passes ; layer++ )
|
||
|
//// {
|
||
|
//// GXTexWrapMode u_mode;
|
||
|
//// GXTexWrapMode v_mode;
|
||
|
//// if ( p_mesh->mp_material->Flags[layer] & MATFLAG_ENVIRONMENT )
|
||
|
//// {
|
||
|
//// p_tex = NULL;
|
||
|
//// u_mode = GX_REPEAT;
|
||
|
//// v_mode = GX_REPEAT;
|
||
|
//// }
|
||
|
//// else
|
||
|
//// {
|
||
|
//// p_tex = &p_mesh->mp_uvBuffer[2*uv_set];
|
||
|
//// u_mode = p_mesh->mp_material->UVAddressing[layer] & (1<<0) ? GX_CLAMP : GX_REPEAT;
|
||
|
//// v_mode = p_mesh->mp_material->UVAddressing[layer] & (1<<1) ? GX_CLAMP : GX_REPEAT;
|
||
|
//// }
|
||
|
//// uv_set++;
|
||
|
////
|
||
|
//// multi_add_texture ( p_tex, p_mesh->m_num_uv_sets, p_mesh->mp_material->uv_slot[layer], p_mesh->mp_material->Flags[layer], layer );
|
||
|
//// }
|
||
|
////
|
||
|
//// multi_end( p_mesh, 0 );
|
||
|
//// }
|
||
|
//// }
|
||
|
//// }
|
||
|
//// }
|
||
|
//
|
||
|
// if ( p_scene->m_numHierarchyObjects != 0 )
|
||
|
// {
|
||
|
// // Hierarchical, set to matrix 0.
|
||
|
// GXSetCurrentMtx( GX_PNMTX0 );
|
||
|
// }
|
||
|
GX::SetProjectionv( pm );
|
||
|
g_object++;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* Sets MESH_FLAG_VISIBLE if visible for all meshes in this scene */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
int cull_scene( sScene *p_scene, uint32 flags )
|
||
|
{
|
||
|
int meshes_visible = 0;
|
||
|
|
||
|
// Cull all meshes.
|
||
|
sMesh ** pp_mesh = p_scene->mpp_mesh_list;
|
||
|
|
||
|
for( int e = 0; e < p_scene->m_num_filled_meshes; ++e )
|
||
|
{
|
||
|
sMesh * p_mesh = pp_mesh[e];
|
||
|
if( ( p_mesh->m_flags & sMesh::MESH_FLAG_ACTIVE ) && ( p_mesh->GetVisibility() & EngineGlobals.viewport ) )
|
||
|
{
|
||
|
Mth::Vector sphere = p_mesh->mp_dl->m_sphere;
|
||
|
|
||
|
// Frustum cull this set of meshes, using the associated bounding box.
|
||
|
if( frustum_check_sphere( sphere ))
|
||
|
{
|
||
|
// Sphere is visible.
|
||
|
if( ( flags & vRENDER_OCCLUDED ) )
|
||
|
{
|
||
|
if ( TestSphereAgainstOccluders( &sphere ) )
|
||
|
{
|
||
|
// Occluded.
|
||
|
p_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Not occluded.
|
||
|
p_mesh->m_flags |= sMesh::MESH_FLAG_VISIBLE;
|
||
|
++meshes_visible;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sphere being visible is enough.
|
||
|
p_mesh->m_flags |= sMesh::MESH_FLAG_VISIBLE;
|
||
|
++meshes_visible;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Sphere not visible.
|
||
|
p_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Force to be not visible.
|
||
|
p_mesh->m_flags &= ~sMesh::MESH_FLAG_VISIBLE;
|
||
|
}
|
||
|
}
|
||
|
return meshes_visible;
|
||
|
|
||
|
// make_scene_visible( p_scene );
|
||
|
// return p_scene->m_num_filled_meshes;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* Sets MESH_FLAG_VISIBLE for all meshes in this scene. */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
void make_scene_visible( sScene *p_scene )
|
||
|
{
|
||
|
// Set all meshes to be visible.
|
||
|
sMesh ** pp_mesh = p_scene->mpp_mesh_list;
|
||
|
|
||
|
for( int e = 0; e < p_scene->m_num_filled_meshes; ++e )
|
||
|
{
|
||
|
if( ( pp_mesh[e]->m_flags & sMesh::MESH_FLAG_ACTIVE ) && ( pp_mesh[e]->GetVisibility() & EngineGlobals.viewport ) )
|
||
|
{
|
||
|
pp_mesh[e]->m_flags |= sMesh::MESH_FLAG_VISIBLE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void render_begin( void )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
void render_end( void )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
} // namespace NxNgc
|
||
|
|
||
|
|
||
|
|