mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
456 lines
13 KiB
C++
456 lines
13 KiB
C++
|
/*****************************************************************************
|
||
|
** **
|
||
|
** Neversoft Entertainment. **
|
||
|
** **
|
||
|
** Copyright (C) 2000 - All Rights Reserved **
|
||
|
** **
|
||
|
******************************************************************************
|
||
|
** **
|
||
|
** Project: THPS4 **
|
||
|
** **
|
||
|
** Module: vu1context **
|
||
|
** **
|
||
|
** File name: vu1context.cpp **
|
||
|
** **
|
||
|
** Created by: 00/00/00 - mrd **
|
||
|
** **
|
||
|
** Description: sends contextual setup data to vu1 float registers **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Includes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <core/defines.h>
|
||
|
#include <core/math.h>
|
||
|
#include <sys/timer.h>
|
||
|
#include "geomnode.h"
|
||
|
#include "vu1context.h"
|
||
|
#include "vu1code.h"
|
||
|
#include "render.h"
|
||
|
#include "dma.h"
|
||
|
#include "vif.h"
|
||
|
#include "gif.h"
|
||
|
#include "gs.h"
|
||
|
#include "light.h"
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** DBG Information **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
namespace NxPs2
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Externals **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Defines **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Types **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Data **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Prototypes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
CVu1Context::CVu1Context()
|
||
|
{
|
||
|
Dbg_Assert("Don't use this constructor!");
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::Init()
|
||
|
{
|
||
|
uint8 *dma_ploc = dma::pLoc;
|
||
|
|
||
|
//dma::pLoc = (uint8 *)&m_stmask;
|
||
|
dma::pLoc = (uint8 *)&m_stmask;
|
||
|
vu1::Loc = 0;
|
||
|
|
||
|
// set vifcodes
|
||
|
vif::STMASK(0); // mp_light_group = NULL; in a very cheeky way
|
||
|
vif::STCYCL(1,1);
|
||
|
vif::UNPACK(0,V4_32,STD_CTXT_SIZE+1,REL,UNSIGNED,0);
|
||
|
|
||
|
// set m_giftag
|
||
|
gif::Tag1(gs::NOP, 1, PACKED, 0, 0, 0, STD_CTXT_SIZE, VU1_ADDR(L_VF12));
|
||
|
|
||
|
//SetExtended(false);
|
||
|
|
||
|
dma::pLoc = dma_ploc;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::InitExtended()
|
||
|
{
|
||
|
uint8 *dma_ploc = dma::pLoc;
|
||
|
|
||
|
//dma::pLoc = (uint8 *)&m_stmask;
|
||
|
dma::pLoc = (uint8 *)&m_stmask;
|
||
|
vu1::Loc = 0;
|
||
|
|
||
|
// set vifcodes
|
||
|
vif::STMASK(0); // mp_light_group = NULL; in a very cheeky way
|
||
|
vif::STCYCL(1,1);
|
||
|
vif::UNPACK(0,V4_32,EXT_CTXT_SIZE+1,REL,UNSIGNED,0);
|
||
|
|
||
|
// set m_giftag
|
||
|
gif::Tag1(gs::NOP, 1, PACKED, 0, 0, 0, EXT_CTXT_SIZE, VU1_ADDR(L_VF12));
|
||
|
|
||
|
SetExtended(true);
|
||
|
|
||
|
update_lights();
|
||
|
|
||
|
dma::pLoc = dma_ploc;
|
||
|
}
|
||
|
|
||
|
|
||
|
CVu1Context::CVu1Context(const CVu1Context &ctxt)
|
||
|
{
|
||
|
// Mick: Since this does not contain any pointers, it's safe to just copy it
|
||
|
// this cuts down on unwarrented initialization of the various vectors and stuff
|
||
|
// and should be fast as we are quad word aligned.
|
||
|
// Garrett: Even though we have a pointer to a light group, it is still OK to
|
||
|
// use memcpy() since this class doesn't manage the instance it points to.
|
||
|
|
||
|
if (ctxt.IsExtended())
|
||
|
{
|
||
|
memcpy(this, &ctxt, (EXT_CTXT_SIZE+7)*16);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// reduced version
|
||
|
memcpy(this, &ctxt, (STD_CTXT_SIZE+7)*16);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::StandardSetup(Mth::Matrix &localToWorld)
|
||
|
{
|
||
|
// get the local to camera matrix
|
||
|
m_matrix = localToWorld * render::WorldToCamera;
|
||
|
|
||
|
// get the massaged matrix values
|
||
|
Mth::Matrix inv = m_matrix;
|
||
|
inv.InvertUniform();
|
||
|
m_translation = -inv[3] * SUB_INCH_PRECISION;
|
||
|
m_translation[0] = float(int(m_translation[0]));
|
||
|
m_translation[1] = float(int(m_translation[1]));
|
||
|
m_translation[2] = float(int(m_translation[2]));
|
||
|
|
||
|
Mth::Matrix adjusted_matrix = m_matrix;
|
||
|
//m_adjustedMatrix = m_matrix;
|
||
|
adjusted_matrix[3] = -m_translation * m_matrix * RECIPROCAL_SUB_INCH_PRECISION;
|
||
|
|
||
|
// generate the vu1 context data
|
||
|
//m_localToFrustum = m_adjustedMatrix * render::CameraToFrustum;
|
||
|
Mth::Matrix temp;
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&temp,
|
||
|
(sceVu0FVECTOR*)&render::CameraToFrustum,
|
||
|
(sceVu0FVECTOR*)&adjusted_matrix);
|
||
|
//m_localToFrustum = temp;
|
||
|
|
||
|
// m_localToViewport = m_localToFrustum * render::FrustumToViewport;
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&m_localToViewport,
|
||
|
(sceVu0FVECTOR*)&render::FrustumToViewport,
|
||
|
(sceVu0FVECTOR*)&temp);
|
||
|
|
||
|
// Update light directions
|
||
|
if (IsExtended())
|
||
|
{
|
||
|
update_lights();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CVu1Context *CVu1Context::Localise()
|
||
|
{
|
||
|
dma::SetList(NULL);
|
||
|
CVu1Context *p_new_context = (CVu1Context*)dma::pLoc;
|
||
|
|
||
|
if (IsExtended())
|
||
|
{
|
||
|
memcpy(dma::pLoc, this, sizeof(CVu1Context));
|
||
|
dma::pLoc += sizeof(CVu1Context);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// reduced version
|
||
|
memcpy(dma::pLoc, this, (STD_CTXT_SIZE+7)*16);
|
||
|
dma::pLoc += (STD_CTXT_SIZE+7)*16;
|
||
|
}
|
||
|
|
||
|
return p_new_context;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
CVu1Context *CVu1Context::LocaliseExtend()
|
||
|
{
|
||
|
dma::SetList(NULL);
|
||
|
CVu1Context *p_new_context = (CVu1Context*)dma::pLoc;
|
||
|
|
||
|
if (IsExtended())
|
||
|
{
|
||
|
memcpy(dma::pLoc, this, sizeof(CVu1Context));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(dma::pLoc, this, (STD_CTXT_SIZE+7)*16);
|
||
|
p_new_context->InitExtended();
|
||
|
}
|
||
|
dma::pLoc += sizeof(CVu1Context);
|
||
|
|
||
|
return p_new_context;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CVu1Context::HierarchicalSetup(Mth::Matrix &localToParent)
|
||
|
{
|
||
|
// get the local to camera matrix
|
||
|
m_matrix = localToParent * m_matrix;
|
||
|
|
||
|
// get the massaged matrix values
|
||
|
Mth::Matrix temp = m_matrix;
|
||
|
m_translation = -(temp.InvertUniform())[3] * SUB_INCH_PRECISION;
|
||
|
m_translation[0] = float(int(m_translation[0]));
|
||
|
m_translation[1] = float(int(m_translation[1]));
|
||
|
m_translation[2] = float(int(m_translation[2]));
|
||
|
|
||
|
Mth::Matrix adjusted_matrix = m_matrix;
|
||
|
//m_adjustedMatrix = m_matrix;
|
||
|
adjusted_matrix[3] = -m_translation * m_matrix * RECIPROCAL_SUB_INCH_PRECISION;
|
||
|
|
||
|
// generate the vu1 context data
|
||
|
// m_localToFrustum = m_adjustedMatrix * render::CameraToFrustum;
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&temp,
|
||
|
(sceVu0FVECTOR*)&render::CameraToFrustum,
|
||
|
(sceVu0FVECTOR*)&adjusted_matrix);
|
||
|
//m_localToFrustum = temp;
|
||
|
|
||
|
// m_localToViewport = m_localToFrustum * render::FrustumToViewport;
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&m_localToViewport,
|
||
|
(sceVu0FVECTOR*)&render::FrustumToViewport,
|
||
|
(sceVu0FVECTOR*)&temp);
|
||
|
|
||
|
// Update light directions
|
||
|
if (IsExtended())
|
||
|
{
|
||
|
update_lights();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Mick: This is taking 1.5% of our precious CPU time
|
||
|
void CVu1Context::update_lights()
|
||
|
{
|
||
|
Mth::Matrix temp;
|
||
|
temp[W].Set(0.0f,0.0f,0.0f,1.0f);
|
||
|
|
||
|
// light vectors
|
||
|
if (mp_light_group)
|
||
|
{
|
||
|
temp[0] = mp_light_group->GetDirection(0);
|
||
|
temp[1] = mp_light_group->GetDirection(1);
|
||
|
temp[2] = mp_light_group->GetDirection(2);
|
||
|
|
||
|
temp *= render::WorldToCamera;
|
||
|
temp.Transpose();
|
||
|
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&m_lightVecsX,
|
||
|
(sceVu0FVECTOR*)&temp,
|
||
|
(sceVu0FVECTOR*)&m_matrix);
|
||
|
|
||
|
m_ambientColour = mp_light_group->GetAmbientColor() * 1.0f/128.0f;
|
||
|
m_lightColour0 = mp_light_group->GetDiffuseColor(0) * 1.0f/128.0f;
|
||
|
m_lightColour1 = mp_light_group->GetDiffuseColor(1) * 1.0f/128.0f;
|
||
|
m_lightColour2 = mp_light_group->GetDiffuseColor(2) * 1.0f/128.0f;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp[0] = CLightGroup::sGetDefaultDirection(0);
|
||
|
temp[1] = CLightGroup::sGetDefaultDirection(1);
|
||
|
temp[2] = CLightGroup::sGetDefaultDirection(2);
|
||
|
|
||
|
temp *= render::WorldToCamera;
|
||
|
temp.Transpose();
|
||
|
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&m_lightVecsX,
|
||
|
(sceVu0FVECTOR*)&temp,
|
||
|
(sceVu0FVECTOR*)&m_matrix);
|
||
|
|
||
|
m_ambientColour = CLightGroup::sGetDefaultAmbientColor() * 1.0f/128.0f;
|
||
|
m_lightColour0 = CLightGroup::sGetDefaultDiffuseColor(0) * 1.0f/128.0f;
|
||
|
m_lightColour1 = CLightGroup::sGetDefaultDiffuseColor(1) * 1.0f/128.0f;
|
||
|
m_lightColour2 = CLightGroup::sGetDefaultDiffuseColor(2) * 1.0f/128.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::SetupAsSky()
|
||
|
{
|
||
|
// get the local to camera matrix
|
||
|
m_matrix = render::WorldToCamera;
|
||
|
|
||
|
// get the massaged matrix values
|
||
|
m_matrix[3].Set(0,0,0,1);
|
||
|
m_translation.Set(0,0,0,1);
|
||
|
|
||
|
Mth::Matrix adjusted_matrix = m_matrix;
|
||
|
//m_adjustedMatrix = m_matrix;
|
||
|
adjusted_matrix.ScaleLocal(Mth::Vector(RECIPROCAL_SUB_INCH_PRECISION, RECIPROCAL_SUB_INCH_PRECISION, RECIPROCAL_SUB_INCH_PRECISION, 1.0f));
|
||
|
|
||
|
// generate the vu1 context data
|
||
|
//m_viewportScale = render::SkyViewportScale;
|
||
|
//m_viewportOffset = render::SkyViewportOffset;
|
||
|
//m_localToFrustum = adjusted_matrix * render::CameraToFrustum;
|
||
|
m_localToViewport = adjusted_matrix * render::CameraToFrustum * render::SkyFrustumToViewport;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::AddZPush(float zPush)
|
||
|
{
|
||
|
m_localToViewport[0][2] += m_localToViewport[0][3] * zPush * 16.0f * render::InverseViewportScale[3];
|
||
|
m_localToViewport[1][2] += m_localToViewport[1][3] * zPush * 16.0f * render::InverseViewportScale[3];
|
||
|
m_localToViewport[2][2] += m_localToViewport[2][3] * zPush * 16.0f * render::InverseViewportScale[3];
|
||
|
m_localToViewport[3][2] += m_localToViewport[3][3] * zPush * 16.0f * render::InverseViewportScale[3];
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::WibbleUVs(float *pData, uint Explicit)
|
||
|
{
|
||
|
if (Explicit)
|
||
|
{
|
||
|
m_texOffset[0] = pData[8];
|
||
|
m_texOffset[1] = pData[9];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Get number of vblanks, but reduce it to 24 bits so we don't lose accuracy in the float conversion.
|
||
|
// This will introduce a glitch every 6 days, but that's preferrable to the loss of accuracy.
|
||
|
int vblanks = Tmr::GetVblanks() & 0x00FFFFFF;
|
||
|
|
||
|
// convert to seconds as float
|
||
|
float t = (float)vblanks * (1.0f/60.0f);
|
||
|
float angle;
|
||
|
|
||
|
// u offset
|
||
|
angle = pData[2] * t + pData[6];
|
||
|
angle -= (2.0f*Mth::PI) * (float)(int)(angle * (0.5f/Mth::PI)); // reduce angle mod 2pi
|
||
|
m_texOffset[0] = pData[0] * t + pData[4] * sinf(angle);
|
||
|
m_texOffset[0] += 8.0f;
|
||
|
m_texOffset[0] -= (float)(((int)m_texOffset[0] >> 4) << 4); // reduce offset mod 16
|
||
|
if (m_texOffset[0] < 0.0f) // and put it in the range -8 to +8
|
||
|
m_texOffset[0] += 8.0f;
|
||
|
else
|
||
|
m_texOffset[0] -= 8.0f;
|
||
|
|
||
|
// v offset
|
||
|
angle = pData[3] * t + pData[7];
|
||
|
angle -= (2.0f*Mth::PI) * (float)(int)(angle * (0.5f/Mth::PI)); // reduce angle mod 2pi
|
||
|
m_texOffset[1] = pData[1] * t + pData[5] * sinf(angle);
|
||
|
m_texOffset[1] += 8.0f;
|
||
|
m_texOffset[1] -= (float)(((int)m_texOffset[1] >> 4) << 4); // reduce offset mod 16
|
||
|
if (m_texOffset[1] < 0.0f) // and put it in the range -8 to +8
|
||
|
m_texOffset[1] += 8.0f;
|
||
|
else
|
||
|
m_texOffset[1] -= 8.0f;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::SetShadowVecs(float y)
|
||
|
{
|
||
|
m_texScale = Mth::Vector(0.0078125f, 0.0078125f, 0.0f, 0.0f);
|
||
|
m_texOffset = Mth::Vector(0.5f-0.0078125f*(render::ShadowCameraPosition[X]+RECIPROCAL_SUB_INCH_PRECISION*m_translation[X]),
|
||
|
0.5f-0.0078125f*(render::ShadowCameraPosition[Z]+RECIPROCAL_SUB_INCH_PRECISION*m_translation[Z]),
|
||
|
-((y+36.0f)+RECIPROCAL_SUB_INCH_PRECISION*m_translation[Y]),
|
||
|
0.0f);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::SetColour(CGeomNode *pNode)
|
||
|
{
|
||
|
uint32 rgba = pNode->GetColor();
|
||
|
m_texScale[X] = (float)(rgba & 0xFF) * 0.0078125f;
|
||
|
m_texScale[Y] = (float)(rgba>> 8 & 0xFF) * 0.0078125f;
|
||
|
m_texScale[Z] = (float)(rgba>>16 & 0xFF) * 0.0078125f;
|
||
|
m_texScale[W] = (float)(rgba>>24 ) * 0.0078125f;
|
||
|
}
|
||
|
|
||
|
|
||
|
Mth::Vector *CVu1Context::GetColour()
|
||
|
{
|
||
|
return &m_texScale;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::SetLights(CLightGroup *pLightGroup)
|
||
|
{
|
||
|
mp_light_group = pLightGroup;
|
||
|
update_lights();
|
||
|
}
|
||
|
|
||
|
|
||
|
void CVu1Context::SetReflectionVecs(sint16 uScale, sint16 vScale)
|
||
|
{
|
||
|
Mth::Matrix temp;
|
||
|
float uf,vf;
|
||
|
uf = float(uScale)*(0.5f/256.0f);
|
||
|
vf = float(vScale)*(0.5f/256.0f);
|
||
|
|
||
|
temp[0] = Mth::Vector(uf, 0, 0, 0);
|
||
|
temp[1] = Mth::Vector(0, vf, 0, 0);
|
||
|
temp[2] = Mth::Vector(0, 0, 1.4,0);
|
||
|
temp.Transpose();
|
||
|
|
||
|
sceVu0MulMatrix((sceVu0FVECTOR*)&m_reflVecsX,
|
||
|
(sceVu0FVECTOR*)&temp,
|
||
|
(sceVu0FVECTOR*)&m_matrix);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
} // namespace NxPs2
|
||
|
|
||
|
|
||
|
|
||
|
|