/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
/***************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***************************************************************************
* *
* Project Name : G *
* *
* $Archive:: /Commando/Code/ww3d2/mapper.cpp $*
* *
* $Org Author:: Hector_y $*
* *
* $Author:: Kenny Mitchell *
* *
* $Modtime:: 06/26/02 4:04p $*
* *
* $Revision:: 33 $*
* *
* 06/26/02 KM Matrix name change to avoid MAX conflicts *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "mapper.h"
#include "ww3d.h"
#include "ini.h"
#include "chunkio.h"
#include "w3derr.h"
#include "meshmatdesc.h"
#include "dx8wrapper.h"
#include "wwdebug.h"
#include "matinfo.h"
#include "rendobj.h"
#include "mesh.h"
#include
#include
Random4Class rand4;
inline DWORD F2DW( FLOAT f ) { return *((DWORD*)&f); }
// HY 1/26/01
// Rewritten to use DX 8 texture matrices
TextureMapperClass::TextureMapperClass(unsigned int stage)
{
Stage = stage;
if (Stage >= MeshMatDescClass::MAX_TEX_STAGES) Stage = MeshMatDescClass::MAX_TEX_STAGES - 1;
}
// Scale mapper
// HY 5/16/01
ScaleTextureMapperClass::ScaleTextureMapperClass(const Vector2 &scale, unsigned int stage) :
TextureMapperClass(stage),
Scale(scale)
{
}
ScaleTextureMapperClass::ScaleTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
TextureMapperClass(stage)
{
Scale.U = ini.Get_Float(section, "UScale", 1.0f);
Scale.V = ini.Get_Float(section, "VScale", 1.0f);
}
ScaleTextureMapperClass::ScaleTextureMapperClass(const ScaleTextureMapperClass & src) :
TextureMapperClass(src),
Scale(src.Scale)
{
}
void ScaleTextureMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Disable Texgen
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_PASSTHRU | uv_array_index);
// Tell rasterizer to expect 2D texture coordinates
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void ScaleTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
tex_matrix.Make_Identity();
tex_matrix[0].X = Scale.U;
tex_matrix[1].Y = Scale.V;
}
// Linear Offset Mapper
LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const Vector2 &offset_per_sec,
const Vector2 & start_offset, bool clamp_fix, const Vector2 &scale, unsigned int stage) :
ScaleTextureMapperClass(scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
StartingUVOffset(start_offset),
ClampFix(clamp_fix)
{
CurrentUVOffset = StartingUVOffset;
// HY 5/16/01
// This is horrible disgusting legacy from the unmentionable API we used before
// leaving it unchanged because the artists have worked around it
UVOffsetDeltaPerMS = offset_per_sec * -0.001f;
}
LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
ScaleTextureMapperClass(ini,section,stage),
LastUsedSyncTime(WW3D::Get_Sync_Time())
{
float u_offset_per_sec = ini.Get_Float(section, "UPerSec", 0.0f);
float v_offset_per_sec = ini.Get_Float(section, "VPerSec", 0.0f);
UVOffsetDeltaPerMS = Vector2(u_offset_per_sec, v_offset_per_sec) * -0.001f;
float u_start_offset = ini.Get_Float(section, "UOffset", 0.0f);
float v_start_offset = ini.Get_Float(section, "VOffset", 0.0f);
StartingUVOffset.Set(u_start_offset, v_start_offset);
CurrentUVOffset = StartingUVOffset;
ClampFix = ini.Get_Bool(section, "ClampFix", false);
}
LinearOffsetTextureMapperClass::LinearOffsetTextureMapperClass(const LinearOffsetTextureMapperClass & src) :
ScaleTextureMapperClass(src),
UVOffsetDeltaPerMS(src.UVOffsetDeltaPerMS),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
StartingUVOffset(src.StartingUVOffset),
ClampFix(src.ClampFix)
{
CurrentUVOffset = StartingUVOffset; // Reset a mapper as it is created
}
void LinearOffsetTextureMapperClass::Reset(void)
{
Set_Current_UV_Offset(Vector2(0.0f, 0.0f));
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
void LinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
float del = (float)delta;
float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
// We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
// choke on them. We do this in one of two ways:
// If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
// 0 and 1 with wraparound. This works well for tiled textures.
// If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
// This works well for clamped textures.
if (!ClampFix) {
offset_u = offset_u - WWMath::Floor(offset_u);
offset_v = offset_v - WWMath::Floor(offset_v);
} else {
offset_u = WWMath::Clamp(offset_u, -Scale.X, Scale.X);
offset_v = WWMath::Clamp(offset_v, -Scale.Y, Scale.Y);
}
// Set up the offset matrix
tex_matrix.Make_Identity();
// According to the docs this should work since its 2D
// otherwise change to translate
tex_matrix[0].Z=offset_u;
tex_matrix[0].X=Scale.X;
tex_matrix[1].Z=offset_v;
tex_matrix[1].Y=Scale.Y;
// Update state
CurrentUVOffset.X = offset_u;
CurrentUVOffset.Y = offset_v;
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
// Grid Mapper
// HY 5/16/01
GridTextureMapperClass::GridTextureMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, unsigned int stage) :
TextureMapperClass(stage),
LastFrame(last_frame),
Offset(offset)
{
initialize(fps, gridwidth_log2);
}
GridTextureMapperClass::GridTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
TextureMapperClass(stage)
{
float fps = ini.Get_Float(section, "FPS", 1.0f);
unsigned int gridwidth_log2 = ini.Get_Int(section, "Log2Width", 1);
LastFrame = ini.Get_Int(section, "Last", 0);
Offset = ini.Get_Int(section, "Offset", 0);
initialize(fps, gridwidth_log2);
}
GridTextureMapperClass::GridTextureMapperClass(const GridTextureMapperClass & src) :
TextureMapperClass(src),
Sign(src.Sign),
MSPerFrame(src.MSPerFrame),
OOGridWidth(src.OOGridWidth),
GridWidthLog2(src.GridWidthLog2),
LastFrame(src.LastFrame),
Offset(src.Offset)
{
Reset();
}
void GridTextureMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage), m);
// Disable Texgen
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | uv_array_index);
// Tell rasterizer to expect 2D texture coordinates
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
}
void GridTextureMapperClass::Reset(void)
{
Remainder = 0;
if (Sign >= 0) {
CurrentFrame = Offset;
} else {
CurrentFrame = (LastFrame - 1) - Offset;
}
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
void GridTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
update_temporal_state();
float u_offset, v_offset;
calculate_uv_offset(&u_offset, &v_offset);
// Set up the offset matrix
tex_matrix.Make_Identity();
// According to the docs this should work since its 2D
// otherwise change to translate
tex_matrix[0].Z = u_offset;
tex_matrix[1].Z = v_offset;
}
void GridTextureMapperClass::Set_Frame_Per_Second(float fps)
{
initialize(fps, GridWidthLog2);
}
void GridTextureMapperClass::initialize(float fps, unsigned int gridwidth_log2)
{
unsigned int grid_width = (1 << gridwidth_log2);
if (LastFrame == 0) LastFrame = (grid_width * grid_width);
Offset = Offset % LastFrame;
LastUsedSyncTime = WW3D::Get_Sync_Time();
GridWidthLog2 = gridwidth_log2;
OOGridWidth = 1.0f / (float)(grid_width);
if (fps == 0.0f) {
// Value of MSPerFrame does not matter as long as it is not 0 - sign will multiply results,
// zeroing them out.
Sign = 0;
MSPerFrame = 1;
CurrentFrame = Offset;
} else if (fps < 0.0f) {
Sign = -1;
MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
CurrentFrame = (LastFrame - 1) - Offset;
} else {
Sign = 1;
MSPerFrame = (unsigned int)(1000.0f / fabs(fps));
CurrentFrame = Offset;
}
Remainder = 0;
}
void GridTextureMapperClass::update_temporal_state(void)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
Remainder += delta;
LastUsedSyncTime = now;
int new_frame = (int)CurrentFrame + ((int)(Remainder / MSPerFrame) * Sign);
new_frame=new_frame % LastFrame;
if (new_frame<0) {
CurrentFrame=LastFrame+new_frame;
} else {
CurrentFrame=(unsigned int) new_frame;
}
Remainder = Remainder % MSPerFrame;
}
void GridTextureMapperClass::calculate_uv_offset(float * u_offset, float * v_offset)
{
unsigned int row_mask = ~(0xFFFFFFFF << GridWidthLog2);
unsigned int col_mask = row_mask << GridWidthLog2;
unsigned int x = CurrentFrame & row_mask;
unsigned int y = (CurrentFrame & col_mask) >> GridWidthLog2;
*u_offset = x * OOGridWidth;
*v_offset = y * OOGridWidth;
}
// Rotate Mapper
// HY 5/16/01
RotateTextureMapperClass::RotateTextureMapperClass(float rad_per_sec, const Vector2 ¢er, const Vector2 &scale, unsigned int stage) :
ScaleTextureMapperClass(scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f),
RadiansPerMilliSec(rad_per_sec/1000.0f),
Center(center)
{
}
RotateTextureMapperClass::RotateTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
ScaleTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f)
{
RadiansPerMilliSec=2*WWMATH_PI*ini.Get_Float(section,"Speed",0.1f)/1000.0f;
Center.U=ini.Get_Float(section,"UCenter",0.0f);
Center.V=ini.Get_Float(section,"VCenter",0.0f);
}
RotateTextureMapperClass::RotateTextureMapperClass(const RotateTextureMapperClass & src) :
ScaleTextureMapperClass(src),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
RadiansPerMilliSec(src.RadiansPerMilliSec),
CurrentAngle(0.0f),
Center(src.Center)
{
}
void RotateTextureMapperClass::Reset(void)
{
CurrentAngle = 0.0f;
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
void RotateTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
LastUsedSyncTime=now;
CurrentAngle+=RadiansPerMilliSec * delta;
CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
if (CurrentAngle<0.0f) CurrentAngle+=2*WWMATH_PI;
// Set up the rotation matrix
float c,s;
c=WWMath::Cos(CurrentAngle);
s=WWMath::Sin(CurrentAngle);
tex_matrix.Make_Identity();
// subtract center
// rotate
// add center
// then scale
tex_matrix[0].Set(Scale.X * c, -Scale.X * s, -Scale.X * (c * Center.U - s * Center.V - Center.U), 0.0f);
tex_matrix[1].Set(Scale.Y * s, Scale.Y * c, -Scale.Y * (s * Center.U + c * Center.V - Center.V), 0.0f);
}
// SineLinearOffset Mapper
// HY 5/16/01
SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const Vector3 &uafp, const Vector3 &vafp, const Vector2 &scale, unsigned int stage) :
ScaleTextureMapperClass(scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
UAFP(uafp),
VAFP(vafp),
CurrentAngle(0.0f)
{
}
SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
ScaleTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f)
{
UAFP.X = ini.Get_Float(section, "UAmp", 1.0f);
UAFP.Y = ini.Get_Float(section, "UFreq", 1.0f);
UAFP.Z = ini.Get_Float(section, "UPhase", 0.0f);
VAFP.X = ini.Get_Float(section, "VAmp", 1.0f);
VAFP.Y = ini.Get_Float(section, "VFreq", 1.0f);
VAFP.Z = ini.Get_Float(section, "VPhase", 0.0f);
}
SineLinearOffsetTextureMapperClass::SineLinearOffsetTextureMapperClass(const SineLinearOffsetTextureMapperClass & src) :
ScaleTextureMapperClass(src),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
UAFP(src.UAFP),
VAFP(src.VAFP),
CurrentAngle(0.0f)
{
}
void SineLinearOffsetTextureMapperClass::Reset(void)
{
CurrentAngle = 0.0f;
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
void SineLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
LastUsedSyncTime=now;
const float ms_to_radians=2*WWMATH_PI/1000.0f;
CurrentAngle+=delta*ms_to_radians;
float offset_u=UAFP.X*sin(UAFP.Y*CurrentAngle+UAFP.Z*WWMATH_PI);
float offset_v=VAFP.X*sin(VAFP.Y*CurrentAngle+VAFP.Z*WWMATH_PI);
// Set up the offset matrix
tex_matrix.Make_Identity();
// According to the docs this should work since its 2D
// otherwise change to translate
tex_matrix[0].Z = offset_u;
tex_matrix[0].X = Scale.X;
tex_matrix[1].Z = offset_v;
tex_matrix[1].Y = Scale.Y;
}
// StepLinearOffset Mapper
// HY 5/16/01
StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const Vector2 &step,
float steps_per_sec, bool clamp_fix, const Vector2 &scale, unsigned int stage) :
ScaleTextureMapperClass(scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Step(step),
StepsPerMilliSec(steps_per_sec/1000.0f),
CurrentStep(0.0f,0.0f),
Remainder(0),
ClampFix(clamp_fix)
{
}
StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
ScaleTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentStep(0.0f,0.0f),
Remainder(0)
{
Step.U = ini.Get_Float(section, "UStep", 0.0f);
Step.V = ini.Get_Float(section, "VStep", 0.0f);
StepsPerMilliSec = ini.Get_Float(section, "SPS", 0.0f)/1000.0f;
ClampFix = ini.Get_Bool(section, "ClampFix", false);
}
StepLinearOffsetTextureMapperClass::StepLinearOffsetTextureMapperClass(const StepLinearOffsetTextureMapperClass & src) :
ScaleTextureMapperClass(src),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Step(src.Step),
StepsPerMilliSec(src.StepsPerMilliSec),
CurrentStep(0.0f,0.0f),
Remainder(0),
ClampFix(src.ClampFix)
{
}
void StepLinearOffsetTextureMapperClass::Reset(void)
{
LastUsedSyncTime = WW3D::Get_Sync_Time();
CurrentStep.Set(0.0f,0.0f);
Remainder=0;
}
void StepLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
LastUsedSyncTime=now;
Remainder+=delta;
int num_steps=(int) (StepsPerMilliSec*Remainder);
if (num_steps!=0)
{
CurrentStep+=Step*num_steps;
Remainder-=num_steps/(float)StepsPerMilliSec;
}
// We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
// choke on them. We do this in one of two ways:
// If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
// 0 and 1 with wraparound. This works well for tiled textures.
// If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
// This works well for clamped textures.
if (!ClampFix) {
CurrentStep.U -= WWMath::Floor(CurrentStep.U);
CurrentStep.V -= WWMath::Floor(CurrentStep.V);
} else {
CurrentStep.U = WWMath::Clamp(CurrentStep.U, -Scale.X, Scale.X);
CurrentStep.V = WWMath::Clamp(CurrentStep.V, -Scale.Y, Scale.Y);
}
// Set up the offset matrix
tex_matrix.Make_Identity();
// According to the docs this should work since its 2D
// otherwise change to translate
tex_matrix[0].Z = CurrentStep.U;
tex_matrix[0].X = Scale.X;
tex_matrix[1].Z = CurrentStep.V;
tex_matrix[1].Y = Scale.Y;
}
// ZigZagLinearOffset Mapper
// HY 5/16/01
ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const Vector2 &speed, float period, const Vector2 &scale, unsigned int stage) :
ScaleTextureMapperClass(scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Speed(speed/1000.0f),
Period(period*1000.0f),
Remainder(0)
{
// since we're zigzagging, a negative period is the same as a positive one
if (Period<0.0f) Period=-Period;
Half_Period=0.5f*Period;
}
ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
ScaleTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Remainder(0)
{
Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
Period = ini.Get_Float(section, "Period", 0.0f)*1000.0f;
if (Period<0.0f) Period=-Period;
Half_Period=0.5f*Period;
}
ZigZagLinearOffsetTextureMapperClass::ZigZagLinearOffsetTextureMapperClass(const ZigZagLinearOffsetTextureMapperClass & src) :
ScaleTextureMapperClass(src),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Speed(src.Speed),
Period(src.Period),
Half_Period(src.Half_Period),
Remainder(0)
{
}
void ZigZagLinearOffsetTextureMapperClass::Reset(void)
{
LastUsedSyncTime = WW3D::Get_Sync_Time();
Remainder=0;
}
void ZigZagLinearOffsetTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
LastUsedSyncTime=now;
Remainder+=delta;
float offset_u=0.0f;
float offset_v=0.0f;
if (Period>0.0f)
{
// figure out the fractional number of periods
int num_periods=(int) (Remainder/Period);
Remainder-=num_periods*Period;
float time=0.0f;
if (Remainder>Half_Period) {
time=Period-Remainder;
} else {
time=Remainder;
}
offset_u=Speed.U * time;
offset_v=Speed.V * time;
}
// Set up the offset matrix
tex_matrix.Make_Identity();
// According to the docs this should work since its 2D
// otherwise change to translate
tex_matrix[0].Z = offset_u;
tex_matrix[0].X = Scale.X;
tex_matrix[1].Z = offset_v;
tex_matrix[1].Y = Scale.Y;
}
// ----------------------------------------------------------------------------
//
// Environment mapper calculates the texture coordinates based on
// transformed normals
//
// ----------------------------------------------------------------------------
void ClassicEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera normals
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void ClassicEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
// The canonical environment map
// scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
// and ignore the Z component
tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
void EnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera reflection vector
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void EnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
// The canonical environment map
// scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
// Edge mapper
EdgeMapperClass::EdgeMapperClass(unsigned int stage) :
TextureMapperClass(stage),
VSpeed(0.0f),
UseReflect(false),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
VOffset(0.0f)
{
}
EdgeMapperClass::EdgeMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
TextureMapperClass(stage),
VSpeed(0.0f),
UseReflect(false),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
VOffset(0.0f)
{
VSpeed=ini.Get_Float(section, "VPerSec", 0.0f);
VOffset=ini.Get_Float(section, "VStart", 0.0f);
UseReflect=ini.Get_Bool(section, "UseReflect", false);
}
EdgeMapperClass::EdgeMapperClass(const EdgeMapperClass & src):
TextureMapperClass(src.Stage),
VSpeed(src.VSpeed),
UseReflect(src.UseReflect),
VOffset(src.VOffset),
LastUsedSyncTime(WW3D::Get_Sync_Time())
{
}
void EdgeMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera reflection vector
if (UseReflect)
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
else
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void EdgeMapperClass::Reset(void)
{
LastUsedSyncTime = WW3D::Get_Sync_Time();
VOffset = 0.0f;
}
void EdgeMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now=WW3D::Get_Sync_Time();
float delta=(now-LastUsedSyncTime)*0.001f;
LastUsedSyncTime=now;
VOffset+=delta*VSpeed;
VOffset-=WWMath::Floor(VOffset);
// takes the Z component and
// uses it to index the texture
tex_matrix.Init( 0.0f, 0.0f, 0.5f, 0.5f,
0.0f, 0.0f, 0.0f, VOffset,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
WSEnvMapperClass::WSEnvMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
TextureMapperClass(stage),
Axis(AXISTYPE_Z)
{
char temp[2];
ini.Get_String(section, "Axis", "Z", &temp[0], 2);
switch(temp[0]) {
case 'X':
case 'x':
Axis = AXISTYPE_X;
break;
case 'Y':
case 'y':
Axis = AXISTYPE_Y;
break;
case 'Z':
case 'z':
Axis = AXISTYPE_Z;
break;
default:
Axis = AXISTYPE_Z;
break;
}
}
void WSEnvMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
// The canonical environment map
// scale the normal by (.5,.5) and add (.5,.5) to move it to (0,1) range
switch (Axis) {
case AXISTYPE_X:
tex_matrix.Init( 0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 0.5f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
case AXISTYPE_Y:
tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.0f, 0.5f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
case AXISTYPE_Z:
default:
tex_matrix.Init( 0.5f, 0.0f, 0.0f, 0.5f,
0.0f, 0.5f, 0.0f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
}
// multiply by inverse of view transform
Matrix4x4 mat;
DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
Matrix4x4 mat2( mat[0].X, mat[1].X, mat[2].X, 0.0f,
mat[0].Y, mat[1].Y, mat[2].Y, 0.0f,
mat[0].Z, mat[1].Z, mat[2].Z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
tex_matrix = tex_matrix * mat2;
}
void WSClassicEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera normals
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void WSEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera reflection
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void GridClassicEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera normals
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void GridClassicEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
update_temporal_state();
float u_offset, v_offset;
calculate_uv_offset(&u_offset, &v_offset);
float del = 0.5f * OOGridWidth;
// Set up the offset matrix
tex_matrix.Init( del, 0.0f, 0.0f, u_offset + del,
0.0f, del, 0.0f, v_offset + del,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
void GridEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera space reflection
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
void GridEnvironmentMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
update_temporal_state();
float u_offset, v_offset;
calculate_uv_offset(&u_offset, &v_offset);
float del=0.5f * OOGridWidth;
// Set up the offset matrix
tex_matrix.Init( del, 0.0f, 0.0f, u_offset + del,
0.0f, del, 0.0f, v_offset + del,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
void ScreenMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera space position
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEPOSITION);
// Tell rasterizer what to expect
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_PROJECTED | D3DTTFF_COUNT3);
}
void ScreenMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int delta = WW3D::Get_Sync_Time() - LastUsedSyncTime;
float del = (float)delta;
float offset_u = CurrentUVOffset.X + UVOffsetDeltaPerMS.X * del;
float offset_v = CurrentUVOffset.Y + UVOffsetDeltaPerMS.Y * del;
// We need to clamp these texture coordinates to a reasonable range so the hardware doesn't
// choke on them. We do this in one of two ways:
// If ClampFix is not TRUE we use the fractional part of the offset, restricting it between
// 0 and 1 with wraparound. This works well for tiled textures.
// If ClampFix is TRUE we clamp the offsets between -Scale and +Scale with no wraparound.
// This works well for clamped textures.
if (!ClampFix) {
offset_u = offset_u - WWMath::Floor(offset_u);
offset_v = offset_v - WWMath::Floor(offset_v);
} else {
offset_u = WWMath::Clamp(offset_u, -Scale.X, Scale.X);
offset_v = WWMath::Clamp(offset_v, -Scale.Y, Scale.Y);
}
// multiply by projection matrix
// followed by scale and translation
DX8Wrapper::Get_Transform(D3DTS_PROJECTION, tex_matrix);
tex_matrix[0] *= Scale.X; // entire row since we're pre-multiplying
tex_matrix[1] *= Scale.Y;
Vector4 last(tex_matrix[3]); // this gets the w
last *= offset_u; // multiply by w because the projected flag will divide by w
tex_matrix[0] += last;
last = tex_matrix[3];
last *= offset_v;
tex_matrix[1] += last;
// Update state
CurrentUVOffset.X = offset_u;
CurrentUVOffset.Y = offset_v;
LastUsedSyncTime = WW3D::Get_Sync_Time();
}
RandomTextureMapperClass::RandomTextureMapperClass(float fps, const Vector2 &scale, unsigned int stage):
ScaleTextureMapperClass(scale, stage),
FPMS(fps/1000.0f),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Speed(0.0f,0.0f),
Remainder(0)
{
randomize();
}
RandomTextureMapperClass::RandomTextureMapperClass(const INIClass &ini, const char *section, unsigned int stage):
ScaleTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Remainder(0)
{
FPMS = ini.Get_Float(section, "FPS", 0.0f)/1000.0f;
Speed.U = ini.Get_Float(section, "UPerSec", 0.0f)/1000.0f;
Speed.V = ini.Get_Float(section, "VPerSec", 0.0f)/1000.0f;
randomize();
}
RandomTextureMapperClass::RandomTextureMapperClass(const RandomTextureMapperClass & src):
ScaleTextureMapperClass(src),
FPMS(src.FPMS),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
Speed(src.Speed),
Remainder(0)
{
randomize();
}
void RandomTextureMapperClass::randomize(void)
{
CurrentAngle=2*WWMATH_PI*rand4.Get_Float();
Center.U=rand4.Get_Float();
Center.V=rand4.Get_Float();
}
void RandomTextureMapperClass::Reset(void)
{
LastUsedSyncTime = WW3D::Get_Sync_Time();
Remainder=0;
}
void RandomTextureMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta=now-LastUsedSyncTime;
LastUsedSyncTime=now;
Remainder+=delta;
if (FPMS!=0.0f) {
int num_frames=(int) (Remainder*FPMS);
if (num_frames!=0) {
randomize();
Remainder-=num_frames/FPMS;
}
}
// Set up the random matrix - start with a rotation matrix of 'CurrentAngle' about the Z-axis.
// We apply the scale matrix to the right of the unscaled rotate/offset matrix, because we
// don't want the scaling to affect the offset. So we get:
// [ c -s uoff ] [ Sx 0 0 ] [ cSx -sSy uoff ]
// [ s c voff ] * [ 0 Sy 0 ] = [ sSx cSy voff ]
// [ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ]
float c = cosf(CurrentAngle);
float s = sinf(CurrentAngle);
tex_matrix.Make_Identity();
tex_matrix[0][0] = c * Scale.X;
tex_matrix[0][1] = -s * Scale.Y;
tex_matrix[1][0] = s * Scale.X;
tex_matrix[1][1] = c * Scale.Y;
// Offset matrix
float uoff = Center.U + Remainder * Speed.U;
float voff = Center.V + Remainder * Speed.V;
uoff = fmodf(uoff, 1.0f);
voff = fmodf(voff, 1.0f);
tex_matrix[0].Z = uoff;
tex_matrix[1].Z = voff;
}
// BumpEnv Mapper
// GTH 8/22/01
BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(float rad_per_sec, float scale_factor,
const Vector2 & offset_per_sec, const Vector2 & start_offset, bool clamp_fix,
const Vector2 &scale, unsigned int stage) :
LinearOffsetTextureMapperClass(offset_per_sec, start_offset, clamp_fix, scale, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f),
RadiansPerSecond(rad_per_sec),
ScaleFactor(scale_factor)
{
}
BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(INIClass &ini, char *section, unsigned int stage) :
LinearOffsetTextureMapperClass(ini, section, stage),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f)
{
RadiansPerSecond = 2*WWMATH_PI*ini.Get_Float(section,"BumpRotation",0.0f);
ScaleFactor = ini.Get_Float(section,"BumpScale",1.0f);
}
BumpEnvTextureMapperClass::BumpEnvTextureMapperClass(const BumpEnvTextureMapperClass & src) :
LinearOffsetTextureMapperClass(src),
LastUsedSyncTime(WW3D::Get_Sync_Time()),
CurrentAngle(0.0f),
RadiansPerSecond(src.RadiansPerSecond),
ScaleFactor(src.ScaleFactor)
{
}
void BumpEnvTextureMapperClass::Apply(int uv_array_index)
{
LinearOffsetTextureMapperClass::Apply(uv_array_index);
unsigned int now = WW3D::Get_Sync_Time();
unsigned int delta = now - LastUsedSyncTime;
LastUsedSyncTime=now;
CurrentAngle+=RadiansPerSecond * delta * 0.001f;
CurrentAngle=fmodf(CurrentAngle,2*WWMATH_PI);
// Compute the sine and cosine for the bump matrix
float c,s;
c=ScaleFactor * WWMath::Fast_Cos(CurrentAngle);
s=ScaleFactor * WWMath::Fast_Sin(CurrentAngle);
// Set the Bump Environment Matrix
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT00, F2DW(c));
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT01, F2DW(-s));
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT10, F2DW(s));
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_BUMPENVMAT11, F2DW(c));
}
/*
** Utility functions
*/
void Reset_All_Texture_Mappers(RenderObjClass *robj, bool make_unique)
{
if (robj->Class_ID()==RenderObjClass::CLASSID_MESH) {
MeshClass *mesh=(MeshClass*) robj;
MaterialInfoClass *minfo = robj->Get_Material_Info();
if (minfo && minfo->Has_Time_Variant_Texture_Mappers()) {
if (make_unique) {
mesh->Make_Unique();
minfo->Make_Vertex_Materials_Unique();
}
minfo->Reset_Texture_Mappers();
minfo->Release_Ref();
}
} else {
int num_obj = robj->Get_Num_Sub_Objects();
RenderObjClass *sub_obj;
for (int i = 0; i < num_obj; i++) {
sub_obj = robj->Get_Sub_Object(i);
if (sub_obj) {
Reset_All_Texture_Mappers(sub_obj, make_unique);
sub_obj->Release_Ref();
}
}
}
}
GridWSEnvMapperClass::GridWSEnvMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage):
GridTextureMapperClass(fps, gridwidth_log2, last_frame, offset, stage),
Axis(axis)
{
}
GridWSEnvMapperClass::GridWSEnvMapperClass(const GridWSEnvMapperClass & src) :
GridTextureMapperClass(src),
Axis(src.Axis)
{
}
GridWSEnvMapperClass::GridWSEnvMapperClass(const INIClass &ini, const char *section, unsigned int stage) :
GridTextureMapperClass(ini, section, stage),
Axis(AXISTYPE_Z)
{
char temp[2];
ini.Get_String(section, "Axis", "Z", &temp[0], 2);
switch(temp[0]) {
case 'X':
case 'x':
Axis = AXISTYPE_X;
break;
case 'Y':
case 'y':
Axis = AXISTYPE_Y;
break;
case 'Z':
case 'z':
Axis = AXISTYPE_Z;
break;
default:
Axis = AXISTYPE_Z;
break;
}
}
void GridWSEnvMapperClass::Calculate_Texture_Matrix(Matrix4x4 &tex_matrix)
{
// multiply by inverse of view transform
Matrix4x4 mat;
DX8Wrapper::Get_Transform(D3DTS_VIEW,mat);
Matrix4x4 mv ( mat[0].X, mat[1].X, mat[2].X, 0.0f,
mat[0].Y, mat[1].Y, mat[2].Y, 0.0f,
mat[0].Z, mat[1].Z, mat[2].Z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
update_temporal_state();
float u_offset, v_offset;
calculate_uv_offset(&u_offset, &v_offset);
float del=0.5f * OOGridWidth;
// Set up the offset matrix
Matrix4x4 md;
switch (Axis) {
case AXISTYPE_X:
md.Init( 0.0f, del, 0.0f, u_offset + del,
0.0f, 0.0f, del, v_offset + del,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
case AXISTYPE_Y:
md.Init( del, 0.0f, 0.0f, u_offset + del,
0.0f, 0.0f, del, v_offset + del,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
case AXISTYPE_Z:
default:
md.Init( del, 0.0f, 0.0f, u_offset + del,
0.0f, del, 0.0f, v_offset + del,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
break;
}
// multiply by inverse of view transform, then
// change the world space reflection vector to a UV coordinate
// then offset by the grid coordinate
tex_matrix = md * mv;
}
/***********************************************************************************************
* GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass -- Grid WS Env Map *
* *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage) :
GridWSEnvMapperClass(fps, gridwidth_log2, last_frame, offset, axis, stage)
{
}
GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(const INIClass &ini, const char *section, unsigned int stage):
GridWSEnvMapperClass(ini,section,stage)
{
}
GridWSClassicEnvironmentMapperClass::GridWSClassicEnvironmentMapperClass(const GridWSEnvMapperClass & src):
GridWSEnvMapperClass(src)
{
}
void GridWSClassicEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera normals
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACENORMAL);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}
/***********************************************************************************************
* GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass -- grid ws env *
* *
* *
* *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 1/29/2002 hy : Created. *
*=============================================================================================*/
GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(float fps, unsigned int gridwidth_log2, unsigned int last_frame, unsigned int offset, AxisType axis, unsigned int stage) :
GridWSEnvMapperClass(fps, gridwidth_log2, last_frame, offset, axis, stage)
{
}
GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(const INIClass &ini, const char *section, unsigned int stage):
GridWSEnvMapperClass(ini, section, stage)
{
}
GridWSEnvironmentMapperClass::GridWSEnvironmentMapperClass(const GridWSEnvMapperClass & src):
GridWSEnvMapperClass(src)
{
}
void GridWSEnvironmentMapperClass::Apply(int uv_array_index)
{
// Set up the texture matrix
Matrix4x4 m;
Calculate_Texture_Matrix(m);
DX8Wrapper::Set_Transform((D3DTRANSFORMSTATETYPE) (D3DTS_TEXTURE0+Stage),m);
// Get camera space reflection
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXCOORDINDEX,D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
// Tell rasterizer to expect 2D matrices
DX8Wrapper::Set_DX8_Texture_Stage_State(Stage,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
}