Moved all files except terrainMain.cpp somewhere else - either maths, graphics or renderer directories.
This was SVN commit r313.
This commit is contained in:
parent
591a9ff13f
commit
52f5b707ee
@ -1,303 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: AlphaMapCalculator.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "AlphaMapCalculator.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CAlphaMapCalculator: functionality for calculating which alpha blend map
|
|
||||||
// fits a given shape
|
|
||||||
namespace CAlphaMapCalculator {
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Blend4: structure mapping a blend shape for N,E,S,W to a particular map
|
|
||||||
struct Blend4 {
|
|
||||||
Blend4(BlendShape4 shape,int alphamap) : m_Shape(shape), m_AlphaMap(alphamap) {}
|
|
||||||
|
|
||||||
BlendShape4 m_Shape;
|
|
||||||
int m_AlphaMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Blend8: structure mapping a blend shape for N,NE,E,SE,S,SW,W,NW to a
|
|
||||||
// particular map
|
|
||||||
struct Blend8 {
|
|
||||||
Blend8(BlendShape8 shape,int alphamap) : m_Shape(shape), m_AlphaMap(alphamap) {}
|
|
||||||
|
|
||||||
BlendShape8 m_Shape;
|
|
||||||
int m_AlphaMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Data tables for mapping between shapes and blend maps
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
const Blend4 Blends1Neighbour[] =
|
|
||||||
{
|
|
||||||
Blend4(BlendShape4(1,0,0,0), 12)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const Blend4 Blends2Neighbour[] =
|
|
||||||
{
|
|
||||||
Blend4(BlendShape4(0,1,1,0), 7),
|
|
||||||
Blend4(BlendShape4(1,0,1,0), 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends2Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,0,0,0,0,0,0), 12),
|
|
||||||
Blend8(BlendShape8(1,0,0,0,0,1,0,0), 12),
|
|
||||||
Blend8(BlendShape8(0,1,0,1,0,0,0,0), 0) ,
|
|
||||||
Blend8(BlendShape8(0,1,0,0,0,1,0,0), 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend4 Blends3Neighbour[] =
|
|
||||||
{
|
|
||||||
Blend4(BlendShape4(1,1,1,0), 4)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends3Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,0,0,1,0,0,0), 10),
|
|
||||||
Blend8(BlendShape8(1,1,0,0,0,0,0,1), 12),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,0,0,0,0), 1),
|
|
||||||
Blend8(BlendShape8(0,1,1,0,1,0,0,0), 7),
|
|
||||||
Blend8(BlendShape8(0,0,1,0,1,0,1,0), 4),
|
|
||||||
Blend8(BlendShape8(1,1,0,0,0,1,0,0), 12),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,0,0,0,0), 12),
|
|
||||||
Blend8(BlendShape8(0,0,1,0,1,0,0,1), 7),
|
|
||||||
Blend8(BlendShape8(1,0,0,1,0,1,0,0), 12),
|
|
||||||
Blend8(BlendShape8(0,1,0,1,0,1,0,0), 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends4Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,0,0,1,0,0,1), 10),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,1,0,0,0), 10),
|
|
||||||
Blend8(BlendShape8(1,1,0,0,1,1,0,0), 10),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,0,0,0,1), 12),
|
|
||||||
Blend8(BlendShape8(0,1,1,0,1,1,0,0), 7),
|
|
||||||
Blend8(BlendShape8(1,1,1,1,0,0,0,0), 1),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,0,0,0), 3),
|
|
||||||
Blend8(BlendShape8(0,0,1,0,1,1,0,1), 7),
|
|
||||||
Blend8(BlendShape8(1,0,1,0,1,1,0,0), 4),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,0,1,0,0), 1),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,0,1,0,0), 12),
|
|
||||||
Blend8(BlendShape8(0,1,0,1,0,1,0,1), 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends5Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,1,1,1,0,0,0), 2),
|
|
||||||
Blend8(BlendShape8(1,1,1,1,0,0,0,1), 1),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,0,0,1), 3),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,0,1,0), 11),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,0,1,0,1), 1),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,1,1,0,0), 10),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,1,0,0), 3),
|
|
||||||
Blend8(BlendShape8(1,0,1,0,1,1,0,1), 4),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,0,1,0,1), 12),
|
|
||||||
Blend8(BlendShape8(0,1,1,0,1,1,0,1), 7)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends6Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,1,1,1,1,0,0), 2),
|
|
||||||
Blend8(BlendShape8(1,1,1,1,1,0,1,0), 8),
|
|
||||||
Blend8(BlendShape8(1,1,1,1,0,1,0,1), 1),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,1,1,0), 6),
|
|
||||||
Blend8(BlendShape8(1,1,1,0,1,1,0,1), 3),
|
|
||||||
Blend8(BlendShape8(1,1,0,1,1,1,0,1), 10)
|
|
||||||
};
|
|
||||||
|
|
||||||
const Blend8 Blends7Neighbour8[] =
|
|
||||||
{
|
|
||||||
Blend8(BlendShape8(1,1,1,1,1,1,0,1), 2),
|
|
||||||
Blend8(BlendShape8(1,1,1,1,1,1,1,0), 9)
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// MatchBlendShapeFlipped: test if the given shape can be made to fit the
|
|
||||||
// template in either unflipped state, or by flipping the shape in U or V
|
|
||||||
template<class T>
|
|
||||||
bool MatchBlendShapeFlipped(const T& templateshape,const T& shape,unsigned int& flags)
|
|
||||||
{
|
|
||||||
// test unrotated shape
|
|
||||||
if (shape==templateshape) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test against shape flipped in U
|
|
||||||
T tstShape;
|
|
||||||
templateshape.FlipU(tstShape);
|
|
||||||
if (shape==tstShape) {
|
|
||||||
flags|=BLENDMAP_FLIPU;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test against shape flipped in V
|
|
||||||
templateshape.FlipV(tstShape);
|
|
||||||
if (shape==tstShape) {
|
|
||||||
flags|=BLENDMAP_FLIPV;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no joy; no match by flipping
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// MatchBlendShape: try and find a matching blendmap, and the required flip/
|
|
||||||
// rotation flags, to fit the given shape to the template
|
|
||||||
template<class T>
|
|
||||||
int MatchBlendShape(const T& templateshape,const T& shape,unsigned int& flags)
|
|
||||||
{
|
|
||||||
// try matching unrotated shape first using just flipping
|
|
||||||
if (MatchBlendShapeFlipped(templateshape,shape,flags)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now try iterating through rotations of 90,180,270 degrees
|
|
||||||
T tstShape;
|
|
||||||
templateshape.Rotate90(tstShape);
|
|
||||||
if (MatchBlendShapeFlipped(tstShape,shape,flags)) {
|
|
||||||
// update flags - note if we've flipped in u or v, we need to rotate in
|
|
||||||
// the opposite direction
|
|
||||||
flags|=flags ? BLENDMAP_ROTATE270 : BLENDMAP_ROTATE90;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
templateshape.Rotate180(tstShape);
|
|
||||||
if (MatchBlendShapeFlipped(tstShape,shape,flags)) {
|
|
||||||
flags|=BLENDMAP_ROTATE180;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
templateshape.Rotate270(tstShape);
|
|
||||||
if (MatchBlendShapeFlipped(tstShape,shape,flags)) {
|
|
||||||
// update flags - note if we've flipped in u or v, we need to rotate in
|
|
||||||
// the opposite direction
|
|
||||||
flags|=flags ? BLENDMAP_ROTATE90 : BLENDMAP_ROTATE270;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// LookupBlend: find and return the blendmap fitting the given shape by
|
|
||||||
// iterating through the given data table and testing each shape in flipped and
|
|
||||||
// rotated forms until a match is found
|
|
||||||
template<class S,class T>
|
|
||||||
int LookupBlend(int tableSize,const S* table,const T& shape,unsigned int& flags)
|
|
||||||
{
|
|
||||||
// iterate through known blend shapes
|
|
||||||
for (int b=0;b<tableSize;b++) {
|
|
||||||
const S& blend=table[b];
|
|
||||||
if (MatchBlendShape(blend.m_Shape,shape,flags)) {
|
|
||||||
return blend.m_AlphaMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eh? shouldn't get here if we've correctly considered all possible cases;
|
|
||||||
// keep the compiler happy, and, while we're still debugging possible shapes,
|
|
||||||
// return bad blend to highlight suspect alphamap logic
|
|
||||||
return 13;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Calculate: return the index of the blend map that fits the given shape,
|
|
||||||
// and the set of flip/rotation flags to get the shape correctly oriented
|
|
||||||
int Calculate(BlendShape8 shape,unsigned int& flags)
|
|
||||||
{
|
|
||||||
// assume we're not going to require flipping or rotating
|
|
||||||
flags=0;
|
|
||||||
|
|
||||||
// count number of neighbours
|
|
||||||
int count=0;
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
if (shape[i]) count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count==0) {
|
|
||||||
// no neighbours, just the centre tile has the given texture; use blend circle
|
|
||||||
return 0;
|
|
||||||
} else if (count==8) {
|
|
||||||
// all neighbours have same texture; return code to signal no alphamap required
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
if (count<=4) {
|
|
||||||
// check if we can consider this a BlendShape4 - ie are any of the diagonals (NE,SE,SW,NW) set?
|
|
||||||
if (!shape[1] && !shape[3] && !shape[5] && !shape[7]) {
|
|
||||||
// ok, build a BlendShape4 and use that
|
|
||||||
BlendShape4 shape4;
|
|
||||||
shape4[0]=shape[0];
|
|
||||||
shape4[1]=shape[2];
|
|
||||||
shape4[2]=shape[4];
|
|
||||||
shape4[3]=shape[6];
|
|
||||||
|
|
||||||
switch (count) {
|
|
||||||
case 1:
|
|
||||||
return LookupBlend(sizeof(Blends1Neighbour)/sizeof(Blend4),Blends1Neighbour,shape4,flags);
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return LookupBlend(sizeof(Blends2Neighbour)/sizeof(Blend4),Blends2Neighbour,shape4,flags);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return LookupBlend(sizeof(Blends3Neighbour)/sizeof(Blend4),Blends3Neighbour,shape4,flags);
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
// N,S,E,W have same texture, NE,SE,SW,NW don't; use a blend 4 corners
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// we've got this far, so now we've got to consider the remaining choices, all containing
|
|
||||||
// diagonal elements
|
|
||||||
switch (count) {
|
|
||||||
case 1:
|
|
||||||
// trivial case - just return a circle blend
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return LookupBlend(sizeof(Blends2Neighbour8)/sizeof(Blend8),Blends2Neighbour8,shape,flags);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return LookupBlend(sizeof(Blends3Neighbour8)/sizeof(Blend8),Blends3Neighbour8,shape,flags);
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
return LookupBlend(sizeof(Blends4Neighbour8)/sizeof(Blend8),Blends4Neighbour8,shape,flags);
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
return LookupBlend(sizeof(Blends5Neighbour8)/sizeof(Blend8),Blends5Neighbour8,shape,flags);
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
return LookupBlend(sizeof(Blends6Neighbour8)/sizeof(Blend8),Blends6Neighbour8,shape,flags);
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
return LookupBlend(sizeof(Blends7Neighbour8)/sizeof(Blend8),Blends7Neighbour8,shape,flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shouldn't get here if we've correctly considered all possible cases;
|
|
||||||
// keep the compiler happy, and, while we're still debugging possible shapes,
|
|
||||||
// return bad blend to highlight suspect alphamap logic
|
|
||||||
return 13;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end of namespace
|
|
@ -1,31 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: AlphaMapCalculator.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _ALPHAMAPCALCULATOR_H
|
|
||||||
#define _ALPHAMAPCALCULATOR_H
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "BlendShapes.h"
|
|
||||||
|
|
||||||
// defines for blendmap flipping/rotating
|
|
||||||
#define BLENDMAP_FLIPV 0x01
|
|
||||||
#define BLENDMAP_FLIPU 0x02
|
|
||||||
#define BLENDMAP_ROTATE90 0x04
|
|
||||||
#define BLENDMAP_ROTATE180 0x08
|
|
||||||
#define BLENDMAP_ROTATE270 0x10
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CAlphaMapCalculator: functionality for calculating which alpha blend map
|
|
||||||
// fits a given shape
|
|
||||||
namespace CAlphaMapCalculator {
|
|
||||||
// Calculate: return the index of the blend map that fits the given shape,
|
|
||||||
// and the set of flip/rotation flags to get the shape correctly oriented
|
|
||||||
int Calculate(BlendShape8 shape,unsigned int& flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,142 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: BlendShapes.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _BLENDSHAPES_H
|
|
||||||
#define _BLENDSHAPES_H
|
|
||||||
|
|
||||||
struct BlendShape4
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BlendShape4() {}
|
|
||||||
BlendShape4(int a,int b,int c,int d) {
|
|
||||||
m_Data[0]=a; m_Data[1]=b; m_Data[2]=c; m_Data[3]=d;
|
|
||||||
}
|
|
||||||
|
|
||||||
int& operator[](int index) { return m_Data[index]; }
|
|
||||||
const int& operator[](int index) const { return m_Data[index]; }
|
|
||||||
|
|
||||||
bool operator==(const BlendShape4& lhs) const {
|
|
||||||
return memcmp(m_Data,lhs.m_Data,sizeof(BlendShape4))==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate90(BlendShape4& dst) const {
|
|
||||||
dst[0]=m_Data[3];
|
|
||||||
dst[1]=m_Data[0];
|
|
||||||
dst[2]=m_Data[1];
|
|
||||||
dst[3]=m_Data[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate180(BlendShape4& dst) const {
|
|
||||||
dst[0]=m_Data[2];
|
|
||||||
dst[1]=m_Data[3];
|
|
||||||
dst[2]=m_Data[0];
|
|
||||||
dst[3]=m_Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate270(BlendShape4& dst) const {
|
|
||||||
dst[0]=m_Data[1];
|
|
||||||
dst[1]=m_Data[2];
|
|
||||||
dst[2]=m_Data[3];
|
|
||||||
dst[3]=m_Data[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlipU(BlendShape4& dst) const {
|
|
||||||
dst[0]=m_Data[2];
|
|
||||||
dst[1]=m_Data[1];
|
|
||||||
dst[2]=m_Data[0];
|
|
||||||
dst[3]=m_Data[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlipV(BlendShape4& dst) const {
|
|
||||||
dst[0]=m_Data[0];
|
|
||||||
dst[1]=m_Data[3];
|
|
||||||
dst[2]=m_Data[2];
|
|
||||||
dst[3]=m_Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_Data[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct BlendShape8
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BlendShape8() {}
|
|
||||||
BlendShape8(int a,int b,int c,int d,int e,int f,int g,int h) {
|
|
||||||
m_Data[0]=a; m_Data[1]=b; m_Data[2]=c; m_Data[3]=d;
|
|
||||||
m_Data[4]=e; m_Data[5]=f; m_Data[6]=g; m_Data[7]=h;
|
|
||||||
}
|
|
||||||
|
|
||||||
int& operator[](int index) { return m_Data[index]; }
|
|
||||||
const int& operator[](int index) const { return m_Data[index]; }
|
|
||||||
|
|
||||||
bool operator==(const BlendShape8& lhs) const {
|
|
||||||
return memcmp(m_Data,lhs.m_Data,sizeof(BlendShape8))==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate90(BlendShape8& dst) const {
|
|
||||||
dst[0]=m_Data[6];
|
|
||||||
dst[1]=m_Data[7];
|
|
||||||
dst[2]=m_Data[0];
|
|
||||||
dst[3]=m_Data[1];
|
|
||||||
dst[4]=m_Data[2];
|
|
||||||
dst[5]=m_Data[3];
|
|
||||||
dst[6]=m_Data[4];
|
|
||||||
dst[7]=m_Data[5];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate180(BlendShape8& dst) const {
|
|
||||||
dst[0]=m_Data[4];
|
|
||||||
dst[1]=m_Data[5];
|
|
||||||
dst[2]=m_Data[6];
|
|
||||||
dst[3]=m_Data[7];
|
|
||||||
dst[4]=m_Data[0];
|
|
||||||
dst[5]=m_Data[1];
|
|
||||||
dst[6]=m_Data[2];
|
|
||||||
dst[7]=m_Data[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rotate270(BlendShape8& dst) const {
|
|
||||||
dst[0]=m_Data[2];
|
|
||||||
dst[1]=m_Data[3];
|
|
||||||
dst[2]=m_Data[4];
|
|
||||||
dst[3]=m_Data[5];
|
|
||||||
dst[4]=m_Data[6];
|
|
||||||
dst[5]=m_Data[7];
|
|
||||||
dst[6]=m_Data[0];
|
|
||||||
dst[7]=m_Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlipU(BlendShape8& dst) const {
|
|
||||||
dst[0]=m_Data[4];
|
|
||||||
dst[1]=m_Data[3];
|
|
||||||
dst[2]=m_Data[2];
|
|
||||||
dst[3]=m_Data[1];
|
|
||||||
dst[4]=m_Data[0];
|
|
||||||
dst[5]=m_Data[7];
|
|
||||||
dst[6]=m_Data[6];
|
|
||||||
dst[7]=m_Data[5];
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlipV(BlendShape8& dst) const {
|
|
||||||
dst[0]=m_Data[0];
|
|
||||||
dst[1]=m_Data[7];
|
|
||||||
dst[2]=m_Data[6];
|
|
||||||
dst[3]=m_Data[5];
|
|
||||||
dst[4]=m_Data[4];
|
|
||||||
dst[5]=m_Data[3];
|
|
||||||
dst[6]=m_Data[2];
|
|
||||||
dst[7]=m_Data[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_Data[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Bound.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// necessary includes
|
|
||||||
#include <assert.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include "Bound.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// operator+=: extend this bound to include given bound
|
|
||||||
CBound& CBound::operator+=(const CBound& b)
|
|
||||||
{
|
|
||||||
for (int i=0;i<3;++i) {
|
|
||||||
if (b[0][i]<m_Data[0][i])
|
|
||||||
m_Data[0][i]=b[0][i];
|
|
||||||
if (b[1][i]>m_Data[1][i])
|
|
||||||
m_Data[1][i]=b[1][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// operator+=: extend this bound to include given point
|
|
||||||
CBound& CBound::operator+=(const CVector3D& pt)
|
|
||||||
{
|
|
||||||
for (int i=0;i<3;++i) {
|
|
||||||
if (pt[i]<m_Data[0][i])
|
|
||||||
m_Data[0][i]=pt[i];
|
|
||||||
else if (pt[i]>m_Data[1][i])
|
|
||||||
m_Data[1][i]=pt[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RayIntersect: intersect ray with this bound; return true
|
|
||||||
// if ray hits (and store entry and exit times), or false
|
|
||||||
// otherwise
|
|
||||||
// note: incoming ray direction must be normalised
|
|
||||||
bool CBound::RayIntersect(const CVector3D& origin,const CVector3D& dir,
|
|
||||||
float& tmin,float& tmax) const
|
|
||||||
{
|
|
||||||
float t1,t2;
|
|
||||||
float tnear,tfar;
|
|
||||||
|
|
||||||
if (dir[0]==0) {
|
|
||||||
if (origin[0]<m_Data[0][0] || origin[0]>m_Data[1][0])
|
|
||||||
return false;
|
|
||||||
else {
|
|
||||||
tnear=(float) FLT_MIN;
|
|
||||||
tfar=(float) FLT_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t1=(m_Data[0][0]-origin[0])/dir[0];
|
|
||||||
t2=(m_Data[1][0]-origin[0])/dir[0];
|
|
||||||
|
|
||||||
if (dir[0]<0) {
|
|
||||||
tnear = t2;
|
|
||||||
tfar = t1;
|
|
||||||
} else {
|
|
||||||
tnear = t1;
|
|
||||||
tfar = t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tfar<0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir[1]==0 && (origin[1]<m_Data[0][1] || origin[1]>m_Data[1][1]))
|
|
||||||
return false;
|
|
||||||
else {
|
|
||||||
t1=(m_Data[0][1]-origin[1])/dir[1];
|
|
||||||
t2=(m_Data[1][1]-origin[1])/dir[1];
|
|
||||||
|
|
||||||
if (dir[1]<0) {
|
|
||||||
if (t2>tnear)
|
|
||||||
tnear = t2;
|
|
||||||
if (t1<tfar)
|
|
||||||
tfar = t1;
|
|
||||||
} else {
|
|
||||||
if (t1>tnear)
|
|
||||||
tnear = t1;
|
|
||||||
if (t2<tfar)
|
|
||||||
tfar = t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tnear>tfar || tfar<0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir[2]==0 && (origin[2]<m_Data[0][2] || origin[2]>m_Data[1][2]))
|
|
||||||
return false;
|
|
||||||
else {
|
|
||||||
t1=(m_Data[0][2]-origin[2])/dir[2];
|
|
||||||
t2=(m_Data[1][2]-origin[2])/dir[2];
|
|
||||||
|
|
||||||
if (dir[2]<0) {
|
|
||||||
if (t2>tnear)
|
|
||||||
tnear = t2;
|
|
||||||
if (t1<tfar)
|
|
||||||
tfar = t1;
|
|
||||||
} else {
|
|
||||||
if (t1>tnear)
|
|
||||||
tnear = t1;
|
|
||||||
if (t2<tfar)
|
|
||||||
tfar = t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tnear>tfar || tfar<0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmin=tnear;
|
|
||||||
tmax=tfar;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SetEmpty: initialise this bound as empty
|
|
||||||
void CBound::SetEmpty()
|
|
||||||
{
|
|
||||||
m_Data[0]=CVector3D(FLT_MAX,FLT_MAX,FLT_MAX);
|
|
||||||
m_Data[1]=CVector3D(FLT_MIN,FLT_MIN,FLT_MIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Transform: transform this bound by given matrix; return transformed bound
|
|
||||||
// in 'result' parameter - slightly modified version of code in Graphic Gems
|
|
||||||
// (can't remember which one it was, though)
|
|
||||||
void CBound::Transform(const CMatrix3D& m,CBound& result) const
|
|
||||||
{
|
|
||||||
assert(this!=&result);
|
|
||||||
|
|
||||||
for (int i=0;i<3;++i) {
|
|
||||||
// handle translation
|
|
||||||
result[0][i]=result[1][i]=m(3,i);
|
|
||||||
|
|
||||||
// Now find the extreme points by considering the product of the
|
|
||||||
// min and max with each component of matrix
|
|
||||||
for(int j=0;j<3;j++) {
|
|
||||||
float a=m(i,j)*m_Data[0][j];
|
|
||||||
float b=m(i,j)*m_Data[1][j];
|
|
||||||
|
|
||||||
if (a<b) {
|
|
||||||
result[0][i]+=a;
|
|
||||||
result[1][i]+=b;
|
|
||||||
} else {
|
|
||||||
result[0][i]+=b;
|
|
||||||
result[1][i]+=a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Bound.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _BOUND_H
|
|
||||||
#define _BOUND_H
|
|
||||||
|
|
||||||
// necessary includes
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Matrix3D.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CBound: basic axis aligned bounding box class
|
|
||||||
class CBound
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CBound() {}
|
|
||||||
CBound(const CVector3D& min,const CVector3D& max) {
|
|
||||||
m_Data[0]=min; m_Data[1]=max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Transform(const CMatrix3D& m,CBound& result) const;
|
|
||||||
|
|
||||||
CVector3D& operator[](int index) { return m_Data[index]; }
|
|
||||||
const CVector3D& operator[](int index) const { return m_Data[index]; }
|
|
||||||
|
|
||||||
void SetEmpty();
|
|
||||||
|
|
||||||
CBound& operator+=(const CBound& b);
|
|
||||||
CBound& operator+=(const CVector3D& pt);
|
|
||||||
|
|
||||||
bool RayIntersect(const CVector3D& origin,const CVector3D& dir,float& tmin,float& tmax) const;
|
|
||||||
|
|
||||||
float GetVolume() const {
|
|
||||||
CVector3D v=m_Data[1]-m_Data[0];
|
|
||||||
return v.X*v.Y*v.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
CVector3D m_Data[2];
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Camera.Cpp
|
|
||||||
// Last Update: 24/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: CCamera holds a view and a projection matrix.
|
|
||||||
// It also has a frustum which can be used to
|
|
||||||
// cull objects for rendering.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#include "Camera.h"
|
|
||||||
|
|
||||||
CCamera::CCamera ()
|
|
||||||
{
|
|
||||||
// set viewport to something anything should handle, but should be initialised
|
|
||||||
// to window size before use
|
|
||||||
m_ViewPort.m_X = 0;
|
|
||||||
m_ViewPort.m_Y = 0;
|
|
||||||
m_ViewPort.m_Width = 800;
|
|
||||||
m_ViewPort.m_Height = 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
CCamera::~CCamera ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCamera::SetProjection (float nearp, float farp, float fov)
|
|
||||||
{
|
|
||||||
float h, w, Q;
|
|
||||||
|
|
||||||
m_NearPlane = nearp;
|
|
||||||
m_FarPlane = farp;
|
|
||||||
m_FOV = fov;
|
|
||||||
|
|
||||||
float Aspect = (float)m_ViewPort.m_Width/(float)m_ViewPort.m_Height;
|
|
||||||
|
|
||||||
w = 1/tanf (fov*0.5f*Aspect);
|
|
||||||
h = 1/tanf (fov*0.5f);
|
|
||||||
Q = m_FarPlane / (m_FarPlane - m_NearPlane);
|
|
||||||
|
|
||||||
m_ProjMat.SetZero ();
|
|
||||||
m_ProjMat._11 = w;
|
|
||||||
m_ProjMat._22 = h;
|
|
||||||
m_ProjMat._33 = Q;
|
|
||||||
m_ProjMat._34 = -Q*m_NearPlane;
|
|
||||||
m_ProjMat._43 = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Updates the frustum planes. Should be called
|
|
||||||
//everytime the view or projection matrices are
|
|
||||||
//altered.
|
|
||||||
void CCamera::UpdateFrustum ()
|
|
||||||
{
|
|
||||||
CMatrix3D MatFinal;
|
|
||||||
CMatrix3D MatView;
|
|
||||||
|
|
||||||
m_Orientation.GetInverse(MatView);
|
|
||||||
|
|
||||||
MatFinal = m_ProjMat * MatView;
|
|
||||||
|
|
||||||
//get the RIGHT plane
|
|
||||||
m_ViewFrustum.SetNumPlanes (6);
|
|
||||||
|
|
||||||
m_ViewFrustum.m_aPlanes[0].m_Norm.X = MatFinal._41-MatFinal._11;
|
|
||||||
m_ViewFrustum.m_aPlanes[0].m_Norm.Y = MatFinal._42-MatFinal._12;
|
|
||||||
m_ViewFrustum.m_aPlanes[0].m_Norm.Z = MatFinal._43-MatFinal._13;
|
|
||||||
m_ViewFrustum.m_aPlanes[0].m_Dist = MatFinal._44-MatFinal._14;
|
|
||||||
|
|
||||||
//get the LEFT plane
|
|
||||||
m_ViewFrustum.m_aPlanes[1].m_Norm.X = MatFinal._41+MatFinal._11;
|
|
||||||
m_ViewFrustum.m_aPlanes[1].m_Norm.Y = MatFinal._42+MatFinal._12;
|
|
||||||
m_ViewFrustum.m_aPlanes[1].m_Norm.Z = MatFinal._43+MatFinal._13;
|
|
||||||
m_ViewFrustum.m_aPlanes[1].m_Dist = MatFinal._44+MatFinal._14;
|
|
||||||
|
|
||||||
//get the BOTTOM plane
|
|
||||||
m_ViewFrustum.m_aPlanes[2].m_Norm.X = MatFinal._41+MatFinal._21;
|
|
||||||
m_ViewFrustum.m_aPlanes[2].m_Norm.Y = MatFinal._42+MatFinal._22;
|
|
||||||
m_ViewFrustum.m_aPlanes[2].m_Norm.Z = MatFinal._43+MatFinal._23;
|
|
||||||
m_ViewFrustum.m_aPlanes[2].m_Dist = MatFinal._44+MatFinal._24;
|
|
||||||
|
|
||||||
//get the TOP plane
|
|
||||||
m_ViewFrustum.m_aPlanes[3].m_Norm.X = MatFinal._41-MatFinal._21;
|
|
||||||
m_ViewFrustum.m_aPlanes[3].m_Norm.Y = MatFinal._42-MatFinal._22;
|
|
||||||
m_ViewFrustum.m_aPlanes[3].m_Norm.Z = MatFinal._43-MatFinal._23;
|
|
||||||
m_ViewFrustum.m_aPlanes[3].m_Dist = MatFinal._44-MatFinal._24;
|
|
||||||
|
|
||||||
//get the FAR plane
|
|
||||||
m_ViewFrustum.m_aPlanes[4].m_Norm.X = MatFinal._41-MatFinal._31;
|
|
||||||
m_ViewFrustum.m_aPlanes[4].m_Norm.Y = MatFinal._42-MatFinal._32;
|
|
||||||
m_ViewFrustum.m_aPlanes[4].m_Norm.Z = MatFinal._43-MatFinal._33;
|
|
||||||
m_ViewFrustum.m_aPlanes[4].m_Dist = MatFinal._44-MatFinal._34;
|
|
||||||
|
|
||||||
//get the NEAR plane
|
|
||||||
m_ViewFrustum.m_aPlanes[5].m_Norm.X = MatFinal._41+MatFinal._31;
|
|
||||||
m_ViewFrustum.m_aPlanes[5].m_Norm.Y = MatFinal._42+MatFinal._32;
|
|
||||||
m_ViewFrustum.m_aPlanes[5].m_Norm.Z = MatFinal._43+MatFinal._33;
|
|
||||||
m_ViewFrustum.m_aPlanes[5].m_Dist = MatFinal._44+MatFinal._34;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCamera::SetViewPort (SViewPort *viewport)
|
|
||||||
{
|
|
||||||
m_ViewPort.m_X = viewport->m_X;
|
|
||||||
m_ViewPort.m_Y = viewport->m_Y;
|
|
||||||
m_ViewPort.m_Width = viewport->m_Width;
|
|
||||||
m_ViewPort.m_Height = viewport->m_Height;
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Camera.H
|
|
||||||
// Last Update: 24/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: CCamera holds a view and a projection matrix.
|
|
||||||
// It also has a frustum which can be used to
|
|
||||||
// cull objects for rendering.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef CAMERA_H
|
|
||||||
#define CAMERA_H
|
|
||||||
|
|
||||||
#include "Frustum.h"
|
|
||||||
#include "Matrix3D.h"
|
|
||||||
|
|
||||||
//view port
|
|
||||||
struct SViewPort
|
|
||||||
{
|
|
||||||
unsigned int m_X;
|
|
||||||
unsigned int m_Y;
|
|
||||||
unsigned int m_Width;
|
|
||||||
unsigned int m_Height;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class CCamera
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCamera ();
|
|
||||||
~CCamera ();
|
|
||||||
|
|
||||||
//Methods for projection
|
|
||||||
void SetProjection (CMatrix3D *proj) { m_ProjMat = *proj; }
|
|
||||||
void SetProjection (float nearp, float farp, float fov);
|
|
||||||
CMatrix3D GetProjection () { return m_ProjMat; }
|
|
||||||
|
|
||||||
//Updates the frustum planes. Should be called
|
|
||||||
//everytime the view or projection matrices are
|
|
||||||
//altered.
|
|
||||||
void UpdateFrustum ();
|
|
||||||
CFrustum GetFustum () { return m_ViewFrustum; }
|
|
||||||
|
|
||||||
void SetViewPort (SViewPort *viewport);
|
|
||||||
SViewPort GetViewPort () { return m_ViewPort; }
|
|
||||||
|
|
||||||
//getters
|
|
||||||
float GetNearPlane () { return m_NearPlane; }
|
|
||||||
float GetFarPlane () { return m_FarPlane; }
|
|
||||||
float GetFOV () { return m_FOV; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
//This is the orientation matrix. The inverse of this
|
|
||||||
//is the view matrix
|
|
||||||
CMatrix3D m_Orientation;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//keep the projection matrix private
|
|
||||||
//so we can't fiddle with it.
|
|
||||||
CMatrix3D m_ProjMat;
|
|
||||||
|
|
||||||
float m_NearPlane;
|
|
||||||
float m_FarPlane;
|
|
||||||
float m_FOV;
|
|
||||||
SViewPort m_ViewPort;
|
|
||||||
|
|
||||||
CFrustum m_ViewFrustum;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,30 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Color.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _COLOR_H
|
|
||||||
#define _COLOR_H
|
|
||||||
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Vector4D.h"
|
|
||||||
|
|
||||||
// simple defines for 3 and 4 component floating point colors - just map to
|
|
||||||
// corresponding vector types
|
|
||||||
typedef CVector3D RGBColor;
|
|
||||||
typedef CVector4D RGBAColor;
|
|
||||||
|
|
||||||
// SColor4ub: structure for packed RGBA colors
|
|
||||||
struct SColor4ub
|
|
||||||
{
|
|
||||||
u8 R;
|
|
||||||
u8 G;
|
|
||||||
u8 B;
|
|
||||||
u8 A;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,76 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: FilePacker.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "FilePacker.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CFilePacker constructor
|
|
||||||
CFilePacker::CFilePacker()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Write: write out any packed data to file, using given version and magic bits
|
|
||||||
void CFilePacker::Write(const char* filename,u32 version,const char magicstr[4])
|
|
||||||
{
|
|
||||||
FILE* fp=fopen(filename,"wb");
|
|
||||||
if (!fp) {
|
|
||||||
throw CFileOpenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// write magic bits
|
|
||||||
if (fwrite(magicstr,sizeof(char)*4,1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileWriteError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// write version
|
|
||||||
if (fwrite(&version,sizeof(version),1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileWriteError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get size of data
|
|
||||||
u32 datasize=(u32)m_Data.size();
|
|
||||||
if (fwrite(&datasize,sizeof(datasize),1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileWriteError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// write out one big chunk of data
|
|
||||||
if (fwrite(&m_Data[0],datasize,1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileWriteError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// all done
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackRaw: pack given number of bytes onto the end of the data stream
|
|
||||||
void CFilePacker::PackRaw(const void* rawdata,size_t rawdatalen)
|
|
||||||
{
|
|
||||||
u32 start=(u32)m_Data.size();
|
|
||||||
m_Data.resize(m_Data.size()+rawdatalen);
|
|
||||||
memcpy(&m_Data[start],rawdata,rawdatalen);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackString: pack a string onto the end of the data stream
|
|
||||||
void CFilePacker::PackString(const CStr& str)
|
|
||||||
{
|
|
||||||
u32 len=(u32)str.Length();
|
|
||||||
PackRaw(&len,sizeof(len));
|
|
||||||
PackRaw((const char*) str,len);
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: FilePacker.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _FILEPACKER_H
|
|
||||||
#define _FILEPACKER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CFilePacker: class to assist in writing of binary files
|
|
||||||
class CFilePacker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// CFilePacker exceptions
|
|
||||||
class CError { };
|
|
||||||
class CFileOpenError : public CError { };
|
|
||||||
class CFileWriteError : public CError { };
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CFilePacker();
|
|
||||||
|
|
||||||
// Write: write out any packed data to file, using given version and magic bits
|
|
||||||
void Write(const char* filename,u32 version,const char magicstr[4]);
|
|
||||||
|
|
||||||
// PackRaw: pack given number of bytes onto the end of the data stream
|
|
||||||
void PackRaw(const void* rawdata,size_t rawdatalen);
|
|
||||||
// PackString: pack a string onto the end of the data stream
|
|
||||||
void PackString(const CStr& str);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// the output data stream built during pack operations
|
|
||||||
std::vector<u8> m_Data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,101 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: FileUnpacker.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "FileUnpacker.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CFileUnpacker constructor
|
|
||||||
CFileUnpacker::CFileUnpacker() : m_UnpackPos(0), m_Version(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Read: open and read in given file, check magic bits against those given; throw
|
|
||||||
// variety of exceptions for missing files etc
|
|
||||||
void CFileUnpacker::Read(const char* filename,const char magicstr[4])
|
|
||||||
{
|
|
||||||
FILE* fp=fopen(filename,"rb");
|
|
||||||
if (!fp) {
|
|
||||||
throw CFileOpenError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// read magic bits
|
|
||||||
char magic[4];
|
|
||||||
if (fread(magic,sizeof(char)*4,1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check we've got the right kind of file
|
|
||||||
if (strncmp(magic,magicstr,4)!=0) {
|
|
||||||
// nope ..
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileTypeError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get version
|
|
||||||
if (fread(&m_Version,sizeof(m_Version),1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// get size of anim data
|
|
||||||
u32 datasize;
|
|
||||||
if (fread(&datasize,sizeof(datasize),1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate memory and read in a big chunk of data
|
|
||||||
m_Data.resize(datasize);
|
|
||||||
if (fread(&m_Data[0],datasize,1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
throw CFileReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// all done
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// UnpackRaw: unpack given number of bytes from the input stream into the given array
|
|
||||||
// - throws CFileEOFError if the end of the data stream is reached before the given
|
|
||||||
// number of bytes have been read
|
|
||||||
void CFileUnpacker::UnpackRaw(void* rawdata,size_t rawdatalen)
|
|
||||||
{
|
|
||||||
// got enough data to unpack?
|
|
||||||
if (m_UnpackPos+rawdatalen<=m_Data.size()) {
|
|
||||||
// yes .. copy over
|
|
||||||
memcpy(rawdata,&m_Data[m_UnpackPos],rawdatalen);
|
|
||||||
// advance pointer
|
|
||||||
m_UnpackPos+=(u32)rawdatalen;
|
|
||||||
} else {
|
|
||||||
// nope - throw exception
|
|
||||||
throw CFileEOFError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// UnpackString: unpack a string from the raw data stream
|
|
||||||
void CFileUnpacker::UnpackString(CStr& result)
|
|
||||||
{
|
|
||||||
// get string length
|
|
||||||
u32 length;
|
|
||||||
UnpackRaw(&length,sizeof(length));
|
|
||||||
|
|
||||||
// read string into temporary buffer
|
|
||||||
std::vector<char> tmp;
|
|
||||||
tmp.resize(length+1);
|
|
||||||
UnpackRaw(&tmp[0],length);
|
|
||||||
tmp[length]='\0';
|
|
||||||
|
|
||||||
// assign to output
|
|
||||||
result=&tmp[0];
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: FileUnpacker.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _FILEUNPACKER_H
|
|
||||||
#define _FILEUNPACKER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CFileUnpacker: class to assist in reading of binary files
|
|
||||||
class CFileUnpacker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// exceptions thrown by class
|
|
||||||
class CError { };
|
|
||||||
class CFileTypeError : public CError { };
|
|
||||||
class CFileVersionError : public CError { };
|
|
||||||
class CFileOpenError : public CError { };
|
|
||||||
class CFileReadError : public CError { };
|
|
||||||
class CFileEOFError : public CError { };
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CFileUnpacker();
|
|
||||||
|
|
||||||
// Read: open and read in given file, check magic bits against those given; throw
|
|
||||||
// variety of exceptions for missing files etc
|
|
||||||
void Read(const char* filename,const char magicstr[4]);
|
|
||||||
|
|
||||||
// GetVersion: return stored file version
|
|
||||||
u32 GetVersion() const { return m_Version; }
|
|
||||||
|
|
||||||
// UnpackRaw: unpack given number of bytes from the input stream into the given array
|
|
||||||
// - throws CFileEOFError if the end of the data stream is reached before the given
|
|
||||||
// number of bytes have been read
|
|
||||||
void UnpackRaw(void* rawdata,size_t rawdatalen);
|
|
||||||
// UnpackString: unpack a string from the raw data stream
|
|
||||||
void UnpackString(CStr& result);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// the input data stream read from file and used during unpack operations
|
|
||||||
std::vector<u8> m_Data;
|
|
||||||
// current unpack position in stream
|
|
||||||
u32 m_UnpackPos;
|
|
||||||
// version of the file currently being read
|
|
||||||
u32 m_Version;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,144 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Frustum.Cpp
|
|
||||||
// Last Update: 24/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: CFrustum is a collection of planes which define
|
|
||||||
// a viewing space. Usually associated with the
|
|
||||||
// camera, there are 6 planes which define the
|
|
||||||
// view pyramid. But we allow more planes per
|
|
||||||
// frustum which maybe used for portal rendering,
|
|
||||||
// where a portal may have 3 or more edges.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#include "Frustum.h"
|
|
||||||
|
|
||||||
CFrustum::CFrustum ()
|
|
||||||
{
|
|
||||||
m_NumPlanes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFrustum::~CFrustum ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CFrustum::SetNumPlanes (int num)
|
|
||||||
{
|
|
||||||
m_NumPlanes = num;
|
|
||||||
|
|
||||||
//clip it
|
|
||||||
if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
|
|
||||||
m_NumPlanes = MAX_NUM_FRUSTUM_PLANES-1;
|
|
||||||
else if (m_NumPlanes < 0)
|
|
||||||
m_NumPlanes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CFrustum::IsPointVisible (const CVector3D &point) const
|
|
||||||
{
|
|
||||||
PLANESIDE Side;
|
|
||||||
|
|
||||||
for (int i=0; i<m_NumPlanes; i++)
|
|
||||||
{
|
|
||||||
Side = m_aPlanes[i].ClassifyPoint (point);
|
|
||||||
|
|
||||||
if (Side == PS_BACK)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CFrustum::IsSphereVisible (const CVector3D ¢er, float radius) const
|
|
||||||
{
|
|
||||||
for (int i=0; i<m_NumPlanes; i++)
|
|
||||||
{
|
|
||||||
float Dist = m_aPlanes[i].DistanceToPlane (center);
|
|
||||||
|
|
||||||
//is it behind the plane
|
|
||||||
if (Dist < 0)
|
|
||||||
{
|
|
||||||
//if non of it falls in front its outside the
|
|
||||||
//frustum
|
|
||||||
if (-Dist > radius)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CFrustum::IsBoxVisible (const CVector3D &position,const CBound &bounds) const
|
|
||||||
{
|
|
||||||
//basically for every plane we calculate the furthust point
|
|
||||||
//in the box to that plane. If that point is beyond the plane
|
|
||||||
//then the box is not visible
|
|
||||||
CVector3D FarPoint;
|
|
||||||
PLANESIDE Side;
|
|
||||||
CVector3D Min = position+bounds[0];
|
|
||||||
CVector3D Max = position+bounds[1];
|
|
||||||
|
|
||||||
for (int i=0; i<m_NumPlanes; i++)
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.X > 0.0f)
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Y > 0.0f)
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
||||||
{
|
|
||||||
FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
||||||
{
|
|
||||||
FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Y > 0.0f)
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
||||||
{
|
|
||||||
FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
||||||
{
|
|
||||||
FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Side = m_aPlanes[i].ClassifyPoint (FarPoint);
|
|
||||||
|
|
||||||
if (Side == PS_BACK)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Frustum.H
|
|
||||||
// Last Update: 24/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: CFrustum is a collection of planes which define
|
|
||||||
// a viewing space. Usually associated with the
|
|
||||||
// camera, there are 6 planes which define the
|
|
||||||
// view pyramid. But we allow more planes per
|
|
||||||
// frustum which maybe used for portal rendering,
|
|
||||||
// where a portal may have 3 or more edges.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef FRUSTUM_H
|
|
||||||
#define FRUSTUM_H
|
|
||||||
|
|
||||||
#include "Plane.h"
|
|
||||||
#include "Bound.h"
|
|
||||||
|
|
||||||
//10 planes should be enough
|
|
||||||
#define MAX_NUM_FRUSTUM_PLANES (10)
|
|
||||||
|
|
||||||
|
|
||||||
class CFrustum
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CFrustum ();
|
|
||||||
~CFrustum ();
|
|
||||||
|
|
||||||
//Set the number of planes to use for
|
|
||||||
//calculations. This is clipped to
|
|
||||||
//[0,MAX_NUM_FRUSTUM_PLANES]
|
|
||||||
void SetNumPlanes (int num);
|
|
||||||
|
|
||||||
//The following methods return true if the shape is
|
|
||||||
//partially or completely in front of the frustum planes
|
|
||||||
bool IsPointVisible (const CVector3D &point) const;
|
|
||||||
bool IsSphereVisible (const CVector3D ¢er, float radius) const;
|
|
||||||
bool IsBoxVisible (const CVector3D &position,const CBound &bounds) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
//make the planes public for ease of use
|
|
||||||
CPlane m_aPlanes[MAX_NUM_FRUSTUM_PLANES];
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_NumPlanes;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,177 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: HFTracer.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "HFTracer.h"
|
|
||||||
#include "terrain/Terrain.h"
|
|
||||||
#include "terrain/Bound.h"
|
|
||||||
#include "terrain/Vector3D.h"
|
|
||||||
|
|
||||||
extern CTerrain g_Terrain;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CHFTracer constructor
|
|
||||||
CHFTracer::CHFTracer(const u16* hf,u32 mapsize,float cellsize,float heightscale)
|
|
||||||
: m_Heightfield(hf), m_MapSize(mapsize), m_CellSize(cellsize),
|
|
||||||
m_HeightScale(heightscale)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RayTriIntersect: intersect a ray with triangle defined by vertices
|
|
||||||
// v0,v1,v2; return true if ray hits triangle at distance less than dist,
|
|
||||||
// or false otherwise
|
|
||||||
bool CHFTracer::RayTriIntersect(const CVector3D& v0,const CVector3D& v1,const CVector3D& v2,
|
|
||||||
const CVector3D& origin,const CVector3D& dir,float& dist) const
|
|
||||||
{
|
|
||||||
const float EPSILON=0.00001f;
|
|
||||||
|
|
||||||
// calculate edge vectors
|
|
||||||
CVector3D edge0=v1-v0;
|
|
||||||
CVector3D edge1=v2-v0;
|
|
||||||
|
|
||||||
// begin calculating determinant - also used to calculate U parameter
|
|
||||||
CVector3D pvec=dir.Cross(edge1);
|
|
||||||
|
|
||||||
// if determinant is near zero, ray lies in plane of triangle
|
|
||||||
float det = edge0.Dot(pvec);
|
|
||||||
if (fabs(det)<EPSILON)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
float inv_det = 1.0f/det;
|
|
||||||
|
|
||||||
// calculate vector from vert0 to ray origin
|
|
||||||
CVector3D tvec=origin-v0;
|
|
||||||
|
|
||||||
// calculate U parameter, test bounds
|
|
||||||
float u=tvec.Dot(pvec)*inv_det;
|
|
||||||
if (u<-0.01f || u>1.01f)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// prepare to test V parameter
|
|
||||||
CVector3D qvec=tvec.Cross(edge0);
|
|
||||||
|
|
||||||
// calculate V parameter and test bounds
|
|
||||||
float v=dir.Dot(qvec)*inv_det;
|
|
||||||
if (v<0.0f || u+v>1.0f)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// calculate distance to intersection point from ray origin
|
|
||||||
float d=edge1.Dot(qvec)*inv_det;
|
|
||||||
if (d>=0 && d<dist) {
|
|
||||||
dist=d;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CellIntersect: test if ray intersects either of the triangles in the given
|
|
||||||
// cell - return hit result, and distance to hit, if hit occurred
|
|
||||||
bool CHFTracer::CellIntersect(int cx,int cz,CVector3D& origin,CVector3D& dir,float& dist) const
|
|
||||||
{
|
|
||||||
bool res=false;
|
|
||||||
|
|
||||||
// get vertices for this cell
|
|
||||||
CVector3D vpos[4];
|
|
||||||
g_Terrain.CalcPosition(cx,cz,vpos[0]);
|
|
||||||
g_Terrain.CalcPosition(cx+1,cz,vpos[1]);
|
|
||||||
g_Terrain.CalcPosition(cx+1,cz+1,vpos[2]);
|
|
||||||
g_Terrain.CalcPosition(cx,cz+1,vpos[3]);
|
|
||||||
|
|
||||||
dist=1.0e30f;
|
|
||||||
if (RayTriIntersect(vpos[0],vpos[1],vpos[2],origin,dir,dist)) {
|
|
||||||
res=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RayTriIntersect(vpos[0],vpos[2],vpos[3],origin,dir,dist)) {
|
|
||||||
res=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RayIntersect: intersect ray with this heightfield; return true if
|
|
||||||
// intersection occurs (and fill in grid coordinates of intersection), or false
|
|
||||||
// otherwise
|
|
||||||
bool CHFTracer::RayIntersect(CVector3D& origin,CVector3D& dir,int& x,int& z,CVector3D& ipt) const
|
|
||||||
{
|
|
||||||
// intersect first against bounding box
|
|
||||||
CBound bound;
|
|
||||||
bound[0]=CVector3D(0,0,0);
|
|
||||||
bound[1]=CVector3D(m_MapSize*m_CellSize,65535*m_HeightScale,m_MapSize*m_CellSize);
|
|
||||||
|
|
||||||
float tmin,tmax;
|
|
||||||
if (!bound.RayIntersect(origin,dir,tmin,tmax)) {
|
|
||||||
// ray missed world bounds; no intersection
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// project origin onto grid, if necessary, to get starting point for traversal
|
|
||||||
CVector3D traversalPt;
|
|
||||||
if (tmin>0) {
|
|
||||||
traversalPt=origin+dir*tmin;
|
|
||||||
} else {
|
|
||||||
traversalPt=origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup traversal variables
|
|
||||||
int sx=dir.X<0 ? -1 : 1;
|
|
||||||
int sz=dir.Z<0 ? -1 : 1;
|
|
||||||
|
|
||||||
float invCellSize=1.0f/float(m_CellSize);
|
|
||||||
|
|
||||||
float fcx=traversalPt.X*invCellSize;
|
|
||||||
int cx=int(fcx);
|
|
||||||
|
|
||||||
float fcz=traversalPt.Z*invCellSize;
|
|
||||||
int cz=int(fcz);
|
|
||||||
|
|
||||||
float invdx=float(1.0/fabs(dir.X));
|
|
||||||
float invdz=float(1.0/fabs(dir.Z));
|
|
||||||
|
|
||||||
float dist;
|
|
||||||
do {
|
|
||||||
// test current cell
|
|
||||||
if (cx>=0 && cx<int(m_MapSize-1) && cz>=0 && cz<int(m_MapSize-1)) {
|
|
||||||
if (CellIntersect(cx,cz,origin,dir,dist)) {
|
|
||||||
x=cx;
|
|
||||||
z=cz;
|
|
||||||
ipt=origin+dir*dist;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get coords of current cell
|
|
||||||
fcx=traversalPt.X*invCellSize;
|
|
||||||
fcz=traversalPt.Z*invCellSize;
|
|
||||||
|
|
||||||
// get distance to next cell in x,z
|
|
||||||
float dx=(sx==-1) ? fcx-float(cx) : 1-(fcx-float(cx));
|
|
||||||
dx*=invdx;
|
|
||||||
float dz=(sz==-1) ? fcz-float(cz) : 1-(fcz-float(cz));
|
|
||||||
dz*=invdz;
|
|
||||||
|
|
||||||
// advance ..
|
|
||||||
float dist;
|
|
||||||
if (dx<dz) {
|
|
||||||
cx+=sx;
|
|
||||||
dist=dx;
|
|
||||||
} else {
|
|
||||||
cz+=sz;
|
|
||||||
dist=dz;
|
|
||||||
}
|
|
||||||
|
|
||||||
traversalPt+=dir*dist;
|
|
||||||
} while (traversalPt.Y>=0);
|
|
||||||
|
|
||||||
// fell off end of heightmap with no intersection; return a miss
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: HFTracer.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _HFTRACER_H
|
|
||||||
#define _HFTRACER_H
|
|
||||||
|
|
||||||
class CVector3D;
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CHFTracer: a class for determining ray intersections with a heightfield
|
|
||||||
class CHFTracer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor; setup data
|
|
||||||
CHFTracer(const u16* hf,u32 mapsize,float cellsize,float heightscale);
|
|
||||||
|
|
||||||
// intersect ray with this heightfield; return true if intersection
|
|
||||||
// occurs (and fill in grid coordinates and point of intersection), or false otherwise
|
|
||||||
bool RayIntersect(CVector3D& origin,CVector3D& dir,int& x,int& z,CVector3D& ipt) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// intersect a ray with triangle defined by vertices
|
|
||||||
// v0,v1,v2; return true if ray hits triangle at distance less than dist,
|
|
||||||
// or false otherwise
|
|
||||||
bool RayTriIntersect(const CVector3D& v0,const CVector3D& v1,const CVector3D& v2,
|
|
||||||
const CVector3D& origin,const CVector3D& dir,float& dist) const;
|
|
||||||
|
|
||||||
// test if ray intersects either of the triangles in the given
|
|
||||||
bool CellIntersect(int cx,int cz,CVector3D& origin,CVector3D& dir,float& dist) const;
|
|
||||||
|
|
||||||
// the heightfield were tracing
|
|
||||||
const u16* m_Heightfield;
|
|
||||||
// size of the heightfield
|
|
||||||
u32 m_MapSize;
|
|
||||||
// cell size - size of each cell in x and z
|
|
||||||
float m_CellSize;
|
|
||||||
// vertical scale - size of each cell in y
|
|
||||||
float m_HeightScale;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,47 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: LightEnv.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: class describing current lighting environment -
|
|
||||||
// at the minute, this is only sunlight and ambient light
|
|
||||||
// parameters; will be extended to handle dynamic lights at some
|
|
||||||
// later date
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LIGHTENV_H
|
|
||||||
#define __LIGHTENV_H
|
|
||||||
|
|
||||||
#include "Color.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CLightEnv: description of a lighting environment - contains all the
|
|
||||||
// necessary parameters for representation of the lighting within a scenario
|
|
||||||
class CLightEnv
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RGBColor m_SunColor;
|
|
||||||
float m_Elevation;
|
|
||||||
float m_Rotation;
|
|
||||||
RGBColor m_TerrainAmbientColor;
|
|
||||||
RGBColor m_UnitsAmbientColor;
|
|
||||||
|
|
||||||
// get sun direction from a rotation and elevation; defined such that:
|
|
||||||
// 0 rotation = (0,0,1)
|
|
||||||
// PI/2 rotation = (-1,0,0)
|
|
||||||
// 0 elevation = (0,0,0)
|
|
||||||
// PI/2 elevation = (0,-1,0)
|
|
||||||
void GetSunDirection(CVector3D& lightdir) const {
|
|
||||||
lightdir.Y=-float(sin(m_Elevation));
|
|
||||||
float scale=1+lightdir.Y;
|
|
||||||
lightdir.X=scale*float(sin(m_Rotation));
|
|
||||||
lightdir.Z=scale*float(cos(m_Rotation));
|
|
||||||
lightdir.Normalize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||||||
#ifndef _MAPIO_H
|
|
||||||
#define _MAPIO_H
|
|
||||||
|
|
||||||
class CMapIO
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// current file version given to saved maps
|
|
||||||
enum { FILE_VERSION = 2 };
|
|
||||||
// supported file read version - file with version less than this will be reject
|
|
||||||
enum { FILE_READ_VERSION = 1 };
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
// description of a tile for I/O purposes
|
|
||||||
struct STileDesc {
|
|
||||||
// index into the texture array of first texture on tile
|
|
||||||
u16 m_Tex1Index;
|
|
||||||
// index into the texture array of second texture; (0xffff) if none
|
|
||||||
u16 m_Tex2Index;
|
|
||||||
// priority
|
|
||||||
u32 m_Priority;
|
|
||||||
};
|
|
||||||
|
|
||||||
// description of an object for I/O purposes
|
|
||||||
struct SObjectDesc {
|
|
||||||
// index into the object array
|
|
||||||
u16 m_ObjectIndex;
|
|
||||||
// transformation matrix
|
|
||||||
float m_Transform[16];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
|||||||
// switch off warnings before including stl files
|
|
||||||
#pragma warning(disable : 4786) // identifier truncated to 255 chars
|
|
||||||
|
|
||||||
#include "Types.h"
|
|
||||||
#include "MapReader.h"
|
|
||||||
#include "UnitManager.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
|
|
||||||
#include "BaseEntity.h"
|
|
||||||
#include "BaseEntityCollection.h"
|
|
||||||
#include "EntityManager.h"
|
|
||||||
|
|
||||||
#include "terrain/Model.h"
|
|
||||||
#include "terrain/Terrain.h"
|
|
||||||
#include "terrain/TextureManager.h"
|
|
||||||
|
|
||||||
extern CTerrain g_Terrain;
|
|
||||||
extern CLightEnv g_LightEnv;
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
// CMapReader constructor: nothing to do at the minute
|
|
||||||
CMapReader::CMapReader()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
|
|
||||||
void CMapReader::LoadMap(const char* filename)
|
|
||||||
{
|
|
||||||
CFileUnpacker unpacker;
|
|
||||||
unpacker.Read(filename,"PSMP");
|
|
||||||
|
|
||||||
// check version
|
|
||||||
if (unpacker.GetVersion()<FILE_READ_VERSION) {
|
|
||||||
throw CFileUnpacker::CFileVersionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack the data
|
|
||||||
UnpackMap(unpacker);
|
|
||||||
|
|
||||||
// finally, apply data to the world
|
|
||||||
ApplyData(unpacker);
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnpackMap: unpack the given data from the raw data stream into local variables
|
|
||||||
void CMapReader::UnpackMap(CFileUnpacker& unpacker)
|
|
||||||
{
|
|
||||||
// now unpack everything into local data
|
|
||||||
UnpackTerrain(unpacker);
|
|
||||||
UnpackObjects(unpacker);
|
|
||||||
if (unpacker.GetVersion()>=2) {
|
|
||||||
UnpackLightEnv(unpacker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnpackLightEnv: unpack lighting parameters from input stream
|
|
||||||
void CMapReader::UnpackLightEnv(CFileUnpacker& unpacker)
|
|
||||||
{
|
|
||||||
unpacker.UnpackRaw(&m_LightEnv.m_SunColor,sizeof(m_LightEnv.m_SunColor));
|
|
||||||
unpacker.UnpackRaw(&m_LightEnv.m_Elevation,sizeof(m_LightEnv.m_Elevation));
|
|
||||||
unpacker.UnpackRaw(&m_LightEnv.m_Rotation,sizeof(m_LightEnv.m_Rotation));
|
|
||||||
unpacker.UnpackRaw(&m_LightEnv.m_TerrainAmbientColor,sizeof(m_LightEnv.m_TerrainAmbientColor));
|
|
||||||
unpacker.UnpackRaw(&m_LightEnv.m_UnitsAmbientColor,sizeof(m_LightEnv.m_UnitsAmbientColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnpackObjects: unpack world objects from input stream
|
|
||||||
void CMapReader::UnpackObjects(CFileUnpacker& unpacker)
|
|
||||||
{
|
|
||||||
// unpack object types
|
|
||||||
u32 numObjTypes;
|
|
||||||
unpacker.UnpackRaw(&numObjTypes,sizeof(numObjTypes));
|
|
||||||
m_ObjectTypes.resize(numObjTypes);
|
|
||||||
for (uint i=0;i<numObjTypes;i++) {
|
|
||||||
CStr objname;
|
|
||||||
unpacker.UnpackString(objname);
|
|
||||||
|
|
||||||
CObjectEntry* object=g_ObjMan.FindObject((const char*) objname);
|
|
||||||
m_ObjectTypes[i]=object;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack object data
|
|
||||||
u32 numObjects;
|
|
||||||
unpacker.UnpackRaw(&numObjects,sizeof(numObjects));
|
|
||||||
m_Objects.resize(numObjects);
|
|
||||||
unpacker.UnpackRaw(&m_Objects[0],sizeof(SObjectDesc)*numObjects);
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnpackTerrain: unpack the terrain from the end of the input data stream
|
|
||||||
// - data: map size, heightmap, list of textures used by map, texture tile assignments
|
|
||||||
void CMapReader::UnpackTerrain(CFileUnpacker& unpacker)
|
|
||||||
{
|
|
||||||
// unpack map size
|
|
||||||
unpacker.UnpackRaw(&m_MapSize,sizeof(m_MapSize));
|
|
||||||
|
|
||||||
// unpack heightmap
|
|
||||||
u32 verticesPerSide=m_MapSize*PATCH_SIZE+1;
|
|
||||||
m_Heightmap.resize(SQR(verticesPerSide));
|
|
||||||
unpacker.UnpackRaw(&m_Heightmap[0],SQR(verticesPerSide)*sizeof(u16));
|
|
||||||
|
|
||||||
// unpack texture names; find handle for each texture
|
|
||||||
u32 numTextures;
|
|
||||||
unpacker.UnpackRaw(&numTextures,sizeof(numTextures));
|
|
||||||
|
|
||||||
m_TerrainTextures.reserve(numTextures);
|
|
||||||
for (uint i=0;i<numTextures;i++) {
|
|
||||||
CStr texturename;
|
|
||||||
unpacker.UnpackString(texturename);
|
|
||||||
|
|
||||||
Handle handle;
|
|
||||||
CTextureEntry* texentry=g_TexMan.FindTexture(texturename);
|
|
||||||
if (!texentry) {
|
|
||||||
// ack; mismatch between texture datasets?
|
|
||||||
handle=0;
|
|
||||||
} else {
|
|
||||||
handle=texentry->m_Handle;
|
|
||||||
}
|
|
||||||
m_TerrainTextures.push_back(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack tile data
|
|
||||||
u32 tilesPerSide=m_MapSize*PATCH_SIZE;
|
|
||||||
m_Tiles.resize(SQR(tilesPerSide));
|
|
||||||
unpacker.UnpackRaw(&m_Tiles[0],sizeof(STileDesc)*m_Tiles.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyData: take all the input data, and rebuild the scene from it
|
|
||||||
void CMapReader::ApplyData(CFileUnpacker& unpacker)
|
|
||||||
{
|
|
||||||
// initialise the terrain
|
|
||||||
g_Terrain.Initialize(m_MapSize,&m_Heightmap[0]);
|
|
||||||
|
|
||||||
// setup the textures on the minipatches
|
|
||||||
STileDesc* tileptr=&m_Tiles[0];
|
|
||||||
for (u32 j=0;j<m_MapSize;j++) {
|
|
||||||
for (u32 i=0;i<m_MapSize;i++) {
|
|
||||||
for (u32 m=0;m<PATCH_SIZE;m++) {
|
|
||||||
for (u32 k=0;k<PATCH_SIZE;k++) {
|
|
||||||
CMiniPatch& mp=g_Terrain.GetPatch(i,j)->m_MiniPatches[m][k];
|
|
||||||
|
|
||||||
mp.Tex1=m_TerrainTextures[tileptr->m_Tex1Index];
|
|
||||||
mp.Tex1Priority=tileptr->m_Priority;
|
|
||||||
|
|
||||||
tileptr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty out existing units
|
|
||||||
g_UnitMan.DeleteAll();
|
|
||||||
|
|
||||||
// add new objects
|
|
||||||
for (u32 i=0;i<m_Objects.size();i++) {
|
|
||||||
CObjectEntry* objentry=m_ObjectTypes[m_Objects[i].m_ObjectIndex];
|
|
||||||
if (objentry && objentry->m_Model) {
|
|
||||||
// Hijack the standard actor instantiation for actors that correspond to entities.
|
|
||||||
// Not an ideal solution; we'll have to figure out a map format that can define entities seperately or somesuch.
|
|
||||||
|
|
||||||
CBaseEntity* templateObject = g_EntityTemplateCollection.getTemplateByActor( objentry );
|
|
||||||
if( templateObject )
|
|
||||||
{
|
|
||||||
CVector3D orient = ((CMatrix3D*)m_Objects[i].m_Transform)->GetIn();
|
|
||||||
CVector3D position = ((CMatrix3D*)m_Objects[i].m_Transform)->GetTranslation();
|
|
||||||
|
|
||||||
g_EntityManager.create( templateObject, position, atan2( -orient.X, -orient.Z ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CUnit* unit=new CUnit;
|
|
||||||
unit->m_Object=objentry;
|
|
||||||
unit->m_Model=objentry->m_Model ? objentry->m_Model->Clone() : 0;
|
|
||||||
|
|
||||||
CMatrix3D transform;
|
|
||||||
memcpy(&transform._11,m_Objects[i].m_Transform,sizeof(float)*16);
|
|
||||||
unit->m_Model->SetTransform(transform);
|
|
||||||
|
|
||||||
// add this unit to list of units stored in unit manager
|
|
||||||
g_UnitMan.AddUnit(unit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unpacker.GetVersion()>=2) {
|
|
||||||
// copy over the lighting parameters
|
|
||||||
g_LightEnv=m_LightEnv;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
#ifndef _MAPREADER_H
|
|
||||||
#define _MAPREADER_H
|
|
||||||
|
|
||||||
#include "MapIO.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
#include "terrain/LightEnv.h"
|
|
||||||
#include "terrain/FileUnpacker.h"
|
|
||||||
|
|
||||||
class CObjectEntry;
|
|
||||||
|
|
||||||
class CMapReader : public CMapIO
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CMapReader();
|
|
||||||
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
|
|
||||||
void LoadMap(const char* filename);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// UnpackMap: unpack the given data from the raw data stream into local variables
|
|
||||||
void UnpackMap(CFileUnpacker& unpacker);
|
|
||||||
// UnpackTerrain: unpack the terrain from the input stream
|
|
||||||
void UnpackTerrain(CFileUnpacker& unpacker);
|
|
||||||
// UnpackObjects: unpack world objects from the input stream
|
|
||||||
void UnpackObjects(CFileUnpacker& unpacker);
|
|
||||||
// UnpackObjects: unpack lighting parameters from the input stream
|
|
||||||
void UnpackLightEnv(CFileUnpacker& unpacker);
|
|
||||||
|
|
||||||
// ApplyData: take all the input data, and rebuild the scene from it
|
|
||||||
void ApplyData(CFileUnpacker& unpacker);
|
|
||||||
|
|
||||||
// size of map
|
|
||||||
u32 m_MapSize;
|
|
||||||
// heightmap for map
|
|
||||||
std::vector<u16> m_Heightmap;
|
|
||||||
// list of terrain textures used by map
|
|
||||||
std::vector<Handle> m_TerrainTextures;
|
|
||||||
// tile descriptions for each tile
|
|
||||||
std::vector<STileDesc> m_Tiles;
|
|
||||||
// list of object types used by map
|
|
||||||
std::vector<CObjectEntry*> m_ObjectTypes;
|
|
||||||
// descriptions for each objects
|
|
||||||
std::vector<SObjectDesc> m_Objects;
|
|
||||||
// lightenv stored in file
|
|
||||||
CLightEnv m_LightEnv;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,226 +0,0 @@
|
|||||||
// switch off warnings before including stl files
|
|
||||||
#pragma warning(disable : 4786) // identifier truncated to 255 chars
|
|
||||||
|
|
||||||
#include "Types.h"
|
|
||||||
#include "MapWriter.h"
|
|
||||||
#include "UnitManager.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
#include "terrain/Model.h"
|
|
||||||
#include "terrain/Terrain.h"
|
|
||||||
#include "terrain/LightEnv.h"
|
|
||||||
#include "terrain/TextureManager.h"
|
|
||||||
|
|
||||||
extern CTerrain g_Terrain;
|
|
||||||
extern CLightEnv g_LightEnv;
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CMapWriter constructor: nothing to do at the minute
|
|
||||||
CMapWriter::CMapWriter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SaveMap: try to save the current map to the given file
|
|
||||||
void CMapWriter::SaveMap(const char* filename)
|
|
||||||
{
|
|
||||||
CFilePacker packer;
|
|
||||||
|
|
||||||
// build necessary data
|
|
||||||
PackMap(packer);
|
|
||||||
|
|
||||||
// write it out
|
|
||||||
packer.Write(filename,FILE_VERSION,"PSMP");
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GetHandleIndex: return the index of the given handle in the given list; or 0xffff if
|
|
||||||
// handle isn't in list
|
|
||||||
static u16 GetHandleIndex(const Handle handle,const std::vector<Handle>& handles)
|
|
||||||
{
|
|
||||||
for (uint i=0;i<handles.size();i++) {
|
|
||||||
if (handles[i]==handle) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GetObjectIndex: return the index of the given object in the given list; or 0xffff if
|
|
||||||
// object isn't in list
|
|
||||||
static u16 GetObjectIndex(const CObjectEntry* object,const std::vector<CObjectEntry*>& objects)
|
|
||||||
{
|
|
||||||
for (uint i=0;i<objects.size();i++) {
|
|
||||||
if (objects[i]==object) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// EnumTerrainTextures: build lists of textures used by map, and tile descriptions for
|
|
||||||
// each tile on the terrain
|
|
||||||
void CMapWriter::EnumTerrainTextures(std::vector<CStr>& textures,
|
|
||||||
std::vector<STileDesc>& tiles)
|
|
||||||
{
|
|
||||||
// the list of all handles in use
|
|
||||||
std::vector<Handle> handles;
|
|
||||||
|
|
||||||
// resize tile array to required size
|
|
||||||
tiles.resize(SQR(g_Terrain.GetVerticesPerSide()-1));
|
|
||||||
STileDesc* tileptr=&tiles[0];
|
|
||||||
|
|
||||||
// now iterate through all the tiles
|
|
||||||
u32 mapsize=g_Terrain.GetPatchesPerSide();
|
|
||||||
for (u32 j=0;j<mapsize;j++) {
|
|
||||||
for (u32 i=0;i<mapsize;i++) {
|
|
||||||
for (u32 m=0;m<PATCH_SIZE;m++) {
|
|
||||||
for (u32 k=0;k<PATCH_SIZE;k++) {
|
|
||||||
CMiniPatch& mp=g_Terrain.GetPatch(i,j)->m_MiniPatches[m][k];
|
|
||||||
u16 index=u16(GetHandleIndex(mp.Tex1,handles));
|
|
||||||
if (index==0xffff) {
|
|
||||||
index=(u16)handles.size();
|
|
||||||
handles.push_back(mp.Tex1);
|
|
||||||
}
|
|
||||||
|
|
||||||
tileptr->m_Tex1Index=index;
|
|
||||||
tileptr->m_Tex2Index=0xffff;
|
|
||||||
tileptr->m_Priority=mp.Tex1Priority;
|
|
||||||
tileptr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now find the texture names for each handle
|
|
||||||
for (uint i=0;i<handles.size();i++) {
|
|
||||||
CStr texturename;
|
|
||||||
CTextureEntry* texentry=g_TexMan.FindTexture(handles[i]);
|
|
||||||
if (!texentry) {
|
|
||||||
// uh-oh, this shouldn't happen; set texturename to empty string
|
|
||||||
texturename="";
|
|
||||||
} else {
|
|
||||||
texturename=texentry->m_Name;
|
|
||||||
}
|
|
||||||
textures.push_back(texturename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// EnumObjects: build lists of object types used by map, and object descriptions for
|
|
||||||
// each object in the world
|
|
||||||
void CMapWriter::EnumObjects(std::vector<CStr>& objectTypes,std::vector<SObjectDesc>& objects)
|
|
||||||
{
|
|
||||||
// the list of all object entries in use
|
|
||||||
std::vector<CObjectEntry*> objectsInUse;
|
|
||||||
|
|
||||||
// resize object array to required size
|
|
||||||
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
|
|
||||||
objects.resize(units.size());
|
|
||||||
SObjectDesc* objptr=&objects[0];
|
|
||||||
|
|
||||||
// now iterate through all the units
|
|
||||||
for (u32 j=0;j<units.size();j++) {
|
|
||||||
CUnit* unit=units[j];
|
|
||||||
|
|
||||||
u16 index=u16(GetObjectIndex(unit->m_Object,objectsInUse));
|
|
||||||
if (index==0xffff) {
|
|
||||||
index=(u16)objectsInUse.size();
|
|
||||||
objectsInUse.push_back(unit->m_Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
objptr->m_ObjectIndex=index;
|
|
||||||
memcpy(objptr->m_Transform,&unit->m_Model->GetTransform()._11,sizeof(float)*16);
|
|
||||||
objptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now build outgoing objectTypes array
|
|
||||||
for (uint i=0;i<objectsInUse.size();i++) {
|
|
||||||
objectTypes.push_back(objectsInUse[i]->m_Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackMap: pack the current world into a raw data stream
|
|
||||||
void CMapWriter::PackMap(CFilePacker& packer)
|
|
||||||
{
|
|
||||||
// now pack everything up
|
|
||||||
PackTerrain(packer);
|
|
||||||
PackObjects(packer);
|
|
||||||
PackLightEnv(packer);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackLightEnv: pack lighting parameters onto the end of the output data stream
|
|
||||||
void CMapWriter::PackLightEnv(CFilePacker& packer)
|
|
||||||
{
|
|
||||||
packer.PackRaw(&g_LightEnv.m_SunColor,sizeof(g_LightEnv.m_SunColor));
|
|
||||||
packer.PackRaw(&g_LightEnv.m_Elevation,sizeof(g_LightEnv.m_Elevation));
|
|
||||||
packer.PackRaw(&g_LightEnv.m_Rotation,sizeof(g_LightEnv.m_Rotation));
|
|
||||||
packer.PackRaw(&g_LightEnv.m_TerrainAmbientColor,sizeof(g_LightEnv.m_TerrainAmbientColor));
|
|
||||||
packer.PackRaw(&g_LightEnv.m_UnitsAmbientColor,sizeof(g_LightEnv.m_UnitsAmbientColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackObjects: pack world objects onto the end of the output data stream
|
|
||||||
// - data: list of objects types used by map, list of object descriptions
|
|
||||||
void CMapWriter::PackObjects(CFilePacker& packer)
|
|
||||||
{
|
|
||||||
// the list of object types used by map
|
|
||||||
std::vector<CStr> objectTypes;
|
|
||||||
// descriptions of each object
|
|
||||||
std::vector<SObjectDesc> objects;
|
|
||||||
|
|
||||||
// build lists by scanning through the world
|
|
||||||
EnumObjects(objectTypes,objects);
|
|
||||||
|
|
||||||
// pack object types
|
|
||||||
u32 numObjTypes=(u32)objectTypes.size();
|
|
||||||
packer.PackRaw(&numObjTypes,sizeof(numObjTypes));
|
|
||||||
for (uint i=0;i<numObjTypes;i++) {
|
|
||||||
packer.PackString(objectTypes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pack object data
|
|
||||||
u32 numObjects=(u32)objects.size();
|
|
||||||
packer.PackRaw(&numObjects,sizeof(numObjects));
|
|
||||||
packer.PackRaw(&objects[0],sizeof(SObjectDesc)*numObjects);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// PackTerrain: pack the terrain onto the end of the output data stream
|
|
||||||
// - data: map size, heightmap, list of textures used by map, texture tile assignments
|
|
||||||
void CMapWriter::PackTerrain(CFilePacker& packer)
|
|
||||||
{
|
|
||||||
// pack map size
|
|
||||||
u32 mapsize=g_Terrain.GetPatchesPerSide();
|
|
||||||
packer.PackRaw(&mapsize,sizeof(mapsize));
|
|
||||||
|
|
||||||
// pack heightmap
|
|
||||||
packer.PackRaw(g_Terrain.GetHeightMap(),sizeof(u16)*SQR(g_Terrain.GetVerticesPerSide()));
|
|
||||||
|
|
||||||
// the list of textures used by map
|
|
||||||
std::vector<CStr> terrainTextures;
|
|
||||||
// descriptions of each tile
|
|
||||||
std::vector<STileDesc> tiles;
|
|
||||||
|
|
||||||
// build lists by scanning through the terrain
|
|
||||||
EnumTerrainTextures(terrainTextures,tiles);
|
|
||||||
|
|
||||||
// pack texture names
|
|
||||||
u32 numTextures=(u32)terrainTextures.size();
|
|
||||||
packer.PackRaw(&numTextures,sizeof(numTextures));
|
|
||||||
for (uint i=0;i<numTextures;i++) {
|
|
||||||
packer.PackString(terrainTextures[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pack tile data
|
|
||||||
packer.PackRaw(&tiles[0],sizeof(STileDesc)*tiles.size());
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
#ifndef _MAPWRITER_H
|
|
||||||
#define _MAPWRITER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "MapIO.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
#include "terrain/FilePacker.h"
|
|
||||||
|
|
||||||
class CMapWriter : public CMapIO
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CMapWriter();
|
|
||||||
// SaveMap: try to save the current map to the given file
|
|
||||||
void SaveMap(const char* filename);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// PackMap: pack the current world into a raw data stream
|
|
||||||
void PackMap(CFilePacker& packer);
|
|
||||||
// PackTerrain: pack the terrain onto the end of the data stream
|
|
||||||
void PackTerrain(CFilePacker& packer);
|
|
||||||
// PackObjects: pack world objects onto the end of the output data stream
|
|
||||||
void PackObjects(CFilePacker& packer);
|
|
||||||
// PackLightEnv: pack lighting parameters onto the end of the output data stream
|
|
||||||
void PackLightEnv(CFilePacker& packer);
|
|
||||||
|
|
||||||
// EnumTerrainTextures: build lists of textures used by map, and indices into this list
|
|
||||||
// for each tile on the terrain
|
|
||||||
void EnumTerrainTextures(std::vector<CStr>& textures,std::vector<STileDesc>& tileIndices);
|
|
||||||
|
|
||||||
// EnumObjects: build lists of object types used by map, and object descriptions for
|
|
||||||
// each object in the world
|
|
||||||
void EnumObjects(std::vector<CStr>& objectTypes,std::vector<SObjectDesc>& objects);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: MathUtil.H
|
|
||||||
// Last Update: 28/1/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: This file contains some maths related
|
|
||||||
// utility macros and fucntions.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef MATHUTIL_H
|
|
||||||
#define MATHUTIL_H
|
|
||||||
|
|
||||||
#ifndef PI
|
|
||||||
#define PI 3.14159265358979323846f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEGTORAD(a) ((a) * (PI/180.0f))
|
|
||||||
#define RADTODEG(a) ((a) * (180.0f/PI))
|
|
||||||
#define SQR(x) ((x) * (x))
|
|
||||||
//#define MAX(a,b) ((a < b) ? (b) : (a))
|
|
||||||
//#define MIN(a,b) ((a < b) ? (a) : (b))
|
|
||||||
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
|
|
||||||
#define ABS(a) ((a > 0) ? (a) : (-a))
|
|
||||||
|
|
||||||
//extern unsigned int F2DW (float f);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,540 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Matrix3D.Cpp
|
|
||||||
// Last Update: 31/1/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: A Matrix class used for holding and
|
|
||||||
// manipulating transformation info.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#include "Matrix3D.h"
|
|
||||||
#include "Quaternion.h"
|
|
||||||
|
|
||||||
CMatrix3D::CMatrix3D ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CMatrix3D::CMatrix3D(float a11,float a12,float a13,float a14,float a21,float a22,float a23,float a24,
|
|
||||||
float a31,float a32,float a33,float a34,float a41,float a42,float a43,float a44)
|
|
||||||
{
|
|
||||||
_11=a11;
|
|
||||||
_12=a12;
|
|
||||||
_13=a13;
|
|
||||||
_14=a14;
|
|
||||||
|
|
||||||
_21=a21;
|
|
||||||
_22=a22;
|
|
||||||
_23=a23;
|
|
||||||
_24=a24;
|
|
||||||
|
|
||||||
_31=a31;
|
|
||||||
_32=a32;
|
|
||||||
_33=a33;
|
|
||||||
_34=a34;
|
|
||||||
|
|
||||||
_41=a41;
|
|
||||||
_42=a42;
|
|
||||||
_43=a43;
|
|
||||||
_44=a44;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix multiplication
|
|
||||||
CMatrix3D CMatrix3D::operator * (const CMatrix3D &matrix) const
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
|
|
||||||
Temp._11 = _11*matrix._11 +
|
|
||||||
_12*matrix._21 +
|
|
||||||
_13*matrix._31 +
|
|
||||||
_14*matrix._41;
|
|
||||||
|
|
||||||
Temp._12 = _11*matrix._12 +
|
|
||||||
_12*matrix._22 +
|
|
||||||
_13*matrix._32 +
|
|
||||||
_14*matrix._42;
|
|
||||||
|
|
||||||
Temp._13 = _11*matrix._13 +
|
|
||||||
_12*matrix._23 +
|
|
||||||
_13*matrix._33 +
|
|
||||||
_14*matrix._43;
|
|
||||||
|
|
||||||
Temp._14 = _11*matrix._14 +
|
|
||||||
_12*matrix._24 +
|
|
||||||
_13*matrix._34 +
|
|
||||||
_14*matrix._44;
|
|
||||||
|
|
||||||
Temp._21 = _21*matrix._11 +
|
|
||||||
_22*matrix._21 +
|
|
||||||
_23*matrix._31 +
|
|
||||||
_24*matrix._41;
|
|
||||||
|
|
||||||
Temp._22 = _21*matrix._12 +
|
|
||||||
_22*matrix._22 +
|
|
||||||
_23*matrix._32 +
|
|
||||||
_24*matrix._42;
|
|
||||||
|
|
||||||
Temp._23 = _21*matrix._13 +
|
|
||||||
_22*matrix._23 +
|
|
||||||
_23*matrix._33 +
|
|
||||||
_24*matrix._43;
|
|
||||||
|
|
||||||
Temp._24 = _21*matrix._14 +
|
|
||||||
_22*matrix._24 +
|
|
||||||
_23*matrix._34 +
|
|
||||||
_24*matrix._44;
|
|
||||||
|
|
||||||
Temp._31 = _31*matrix._11 +
|
|
||||||
_32*matrix._21 +
|
|
||||||
_33*matrix._31 +
|
|
||||||
_34*matrix._41;
|
|
||||||
|
|
||||||
Temp._32 = _31*matrix._12 +
|
|
||||||
_32*matrix._22 +
|
|
||||||
_33*matrix._32 +
|
|
||||||
_34*matrix._42;
|
|
||||||
|
|
||||||
Temp._33 = _31*matrix._13 +
|
|
||||||
_32*matrix._23 +
|
|
||||||
_33*matrix._33 +
|
|
||||||
_34*matrix._43;
|
|
||||||
|
|
||||||
Temp._34 = _31*matrix._14 +
|
|
||||||
_32*matrix._24 +
|
|
||||||
_33*matrix._34 +
|
|
||||||
_34*matrix._44;
|
|
||||||
|
|
||||||
Temp._41 = _41*matrix._11 +
|
|
||||||
_42*matrix._21 +
|
|
||||||
_43*matrix._31 +
|
|
||||||
_44*matrix._41;
|
|
||||||
|
|
||||||
Temp._42 = _41*matrix._12 +
|
|
||||||
_42*matrix._22 +
|
|
||||||
_43*matrix._32 +
|
|
||||||
_44*matrix._42;
|
|
||||||
|
|
||||||
Temp._43 = _41*matrix._13 +
|
|
||||||
_42*matrix._23 +
|
|
||||||
_43*matrix._33 +
|
|
||||||
_44*matrix._43;
|
|
||||||
|
|
||||||
Temp._44 = _41*matrix._14 +
|
|
||||||
_42*matrix._24 +
|
|
||||||
_43*matrix._34 +
|
|
||||||
_44*matrix._44;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix multiplication/assignment
|
|
||||||
CMatrix3D &CMatrix3D::operator *= (const CMatrix3D &matrix)
|
|
||||||
{
|
|
||||||
CMatrix3D tmp=(*this) * matrix;
|
|
||||||
*this=tmp;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix scaling
|
|
||||||
CMatrix3D CMatrix3D::operator*(float f) const
|
|
||||||
{
|
|
||||||
CMatrix3D tmp;
|
|
||||||
for (int i=0;i<16;i++) {
|
|
||||||
tmp._data[i]=_data[i]*f;
|
|
||||||
}
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix scaling/assignment
|
|
||||||
CMatrix3D& CMatrix3D::operator*=(float f)
|
|
||||||
{
|
|
||||||
for (int i=0;i<16;i++) {
|
|
||||||
_data[i]*=f;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix addition
|
|
||||||
CMatrix3D CMatrix3D::operator+(const CMatrix3D& m) const
|
|
||||||
{
|
|
||||||
CMatrix3D tmp;
|
|
||||||
for (int i=0;i<16;i++) {
|
|
||||||
tmp._data[i]=_data[i]+m._data[i];
|
|
||||||
}
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Matrix addition/assignment
|
|
||||||
CMatrix3D& CMatrix3D::operator+=(const CMatrix3D& m)
|
|
||||||
{
|
|
||||||
for (int i=0;i<16;i++) {
|
|
||||||
_data[i]+=m._data[i];
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sets the identity matrix
|
|
||||||
void CMatrix3D::SetIdentity ()
|
|
||||||
{
|
|
||||||
_11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
|
|
||||||
_21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
|
|
||||||
_31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sets the zero matrix
|
|
||||||
void CMatrix3D::SetZero ()
|
|
||||||
{
|
|
||||||
_11=0.0f; _12=0.0f; _13=0.0f; _14=0.0f;
|
|
||||||
_21=0.0f; _22=0.0f; _23=0.0f; _24=0.0f;
|
|
||||||
_31=0.0f; _32=0.0f; _33=0.0f; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//The following clear the matrix and set the
|
|
||||||
//rotation of each of the 3 axes
|
|
||||||
|
|
||||||
void CMatrix3D::SetXRotation (float angle)
|
|
||||||
{
|
|
||||||
float Cos = cosf (angle);
|
|
||||||
float Sin = sinf (angle);
|
|
||||||
|
|
||||||
_11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
|
|
||||||
_21=0.0f; _22=Cos; _23=-Sin; _24=0.0f;
|
|
||||||
_31=0.0f; _32=Sin; _33=Cos; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::SetYRotation (float angle)
|
|
||||||
{
|
|
||||||
float Cos = cosf (angle);
|
|
||||||
float Sin = sinf (angle);
|
|
||||||
|
|
||||||
_11=Cos; _12=0.0f; _13=Sin; _14=0.0f;
|
|
||||||
_21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
|
|
||||||
_31=-Sin; _32=0.0f; _33=Cos; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::SetZRotation (float angle)
|
|
||||||
{
|
|
||||||
float Cos = cosf (angle);
|
|
||||||
float Sin = sinf (angle);
|
|
||||||
|
|
||||||
_11=Cos; _12=-Sin; _13=0.0f; _14=0.0f;
|
|
||||||
_21=Sin; _22=Cos; _23=0.0f; _24=0.0f;
|
|
||||||
_31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//The following apply a rotation to the matrix
|
|
||||||
//about each of the axes;
|
|
||||||
|
|
||||||
void CMatrix3D::RotateX (float angle)
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
Temp.SetXRotation (angle);
|
|
||||||
|
|
||||||
(*this) = Temp * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::RotateY (float angle)
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
Temp.SetYRotation (angle);
|
|
||||||
|
|
||||||
(*this) = Temp * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::RotateZ (float angle)
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
Temp.SetZRotation (angle);
|
|
||||||
|
|
||||||
(*this) = Temp * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sets the translation of the matrix
|
|
||||||
void CMatrix3D::SetTranslation (float x, float y, float z)
|
|
||||||
{
|
|
||||||
_11=1.0f; _12=0.0f; _13=0.0f; _14=x;
|
|
||||||
_21=0.0f; _22=1.0f; _23=0.0f; _24=y;
|
|
||||||
_31=0.0f; _32=0.0f; _33=1.0f; _34=z;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::SetTranslation(const CVector3D& vector)
|
|
||||||
{
|
|
||||||
SetTranslation (vector.X, vector.Y, vector.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Applies a translation to the matrix
|
|
||||||
void CMatrix3D::Translate (float x, float y, float z)
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
Temp.SetTranslation (x, y, z);
|
|
||||||
|
|
||||||
(*this) = Temp * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::Translate (const CVector3D &vector)
|
|
||||||
{
|
|
||||||
Translate (vector.X, vector.Y, vector.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector3D CMatrix3D::GetTranslation() const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = _14;
|
|
||||||
Temp.Y = _24;
|
|
||||||
Temp.Z = _34;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clears and sets the scaling of the matrix
|
|
||||||
void CMatrix3D::SetScaling (float x_scale, float y_scale, float z_scale)
|
|
||||||
{
|
|
||||||
_11=x_scale; _12=0.0f; _13=0.0f; _14=0.0f;
|
|
||||||
_21=0.0f; _22=y_scale; _23=0.0f; _24=0.0f;
|
|
||||||
_31=0.0f; _32=0.0f; _33=z_scale; _34=0.0f;
|
|
||||||
_41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Scales the matrix
|
|
||||||
void CMatrix3D::Scale (float x_scale, float y_scale, float z_scale)
|
|
||||||
{
|
|
||||||
CMatrix3D Temp;
|
|
||||||
Temp.SetScaling (x_scale, y_scale, z_scale);
|
|
||||||
|
|
||||||
(*this) = Temp * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns the transpose of the matrix. For orthonormal
|
|
||||||
//matrices, this is the same is the inverse matrix
|
|
||||||
void CMatrix3D::GetTranspose(CMatrix3D& result) const
|
|
||||||
{
|
|
||||||
result._11 = _11;
|
|
||||||
result._21 = _12;
|
|
||||||
result._31 = _13;
|
|
||||||
result._41 = _14;
|
|
||||||
|
|
||||||
result._12 = _21;
|
|
||||||
result._22 = _22;
|
|
||||||
result._32 = _23;
|
|
||||||
result._42 = _24;
|
|
||||||
|
|
||||||
result._13 = _31;
|
|
||||||
result._23 = _32;
|
|
||||||
result._33 = _33;
|
|
||||||
result._43 = _34;
|
|
||||||
|
|
||||||
result._14 = _41;
|
|
||||||
result._24 = _42;
|
|
||||||
result._34 = _43;
|
|
||||||
result._44 = _44;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Get a vector which points to the left of the matrix
|
|
||||||
CVector3D CMatrix3D::GetLeft () const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = -_11;
|
|
||||||
Temp.Y = -_21;
|
|
||||||
Temp.Z = -_31;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get a vector which points up from the matrix
|
|
||||||
CVector3D CMatrix3D::GetUp () const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = _12;
|
|
||||||
Temp.Y = _22;
|
|
||||||
Temp.Z = _32;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get a vector which points to front of the matrix
|
|
||||||
CVector3D CMatrix3D::GetIn () const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = _13;
|
|
||||||
Temp.Y = _23;
|
|
||||||
Temp.Z = _33;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Transform a vector by this matrix
|
|
||||||
CVector3D CMatrix3D::Transform (const CVector3D &vector) const
|
|
||||||
{
|
|
||||||
CVector3D result;
|
|
||||||
Transform(vector,result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::Transform(const CVector3D& vector,CVector3D& result) const
|
|
||||||
{
|
|
||||||
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
|
|
||||||
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
|
|
||||||
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Transform a vector by this matrix
|
|
||||||
CVector4D CMatrix3D::Transform(const CVector4D &vector) const
|
|
||||||
{
|
|
||||||
CVector4D result;
|
|
||||||
Transform(vector,result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::Transform(const CVector4D& vector,CVector4D& result) const
|
|
||||||
{
|
|
||||||
result[0] = _11*vector[0] + _12*vector[1] + _13*vector[2] + _14*vector[3];
|
|
||||||
result[1] = _21*vector[0] + _22*vector[1] + _23*vector[2] + _24*vector[3];
|
|
||||||
result[2] = _31*vector[0] + _32*vector[1] + _33*vector[2] + _34*vector[3];
|
|
||||||
result[3] = _41*vector[0] + _42*vector[1] + _43*vector[2] + _44*vector[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only rotate (not translate) a vector by this matrix
|
|
||||||
CVector3D CMatrix3D::Rotate (const CVector3D& vector) const
|
|
||||||
{
|
|
||||||
CVector3D result;
|
|
||||||
Rotate(vector,result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::Rotate(const CVector3D& vector,CVector3D& result) const
|
|
||||||
{
|
|
||||||
result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
|
|
||||||
result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
|
|
||||||
result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RotateTransposed: rotate a vector by the transpose of this matrix
|
|
||||||
CVector3D CMatrix3D::RotateTransposed(const CVector3D& vector) const
|
|
||||||
{
|
|
||||||
CVector3D result;
|
|
||||||
RotateTransposed(vector,result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RotateTransposed: rotate a vector by the transpose of this matrix
|
|
||||||
void CMatrix3D::RotateTransposed(const CVector3D& vector,CVector3D& result) const
|
|
||||||
{
|
|
||||||
result.X = _11*vector.X + _21*vector.Y + _31*vector.Z;
|
|
||||||
result.Y = _12*vector.X + _22*vector.Y + _32*vector.Z;
|
|
||||||
result.Z = _13*vector.X + _23*vector.Y + _33*vector.Z;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CMatrix3D::GetInverse(CMatrix3D& dst) const
|
|
||||||
{
|
|
||||||
float tmp[12]; // temp array for pairs
|
|
||||||
float src[16]; // array of transpose source matrix
|
|
||||||
float det; // determinant
|
|
||||||
|
|
||||||
// transpose matrix
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
src[i] = _data[i*4];
|
|
||||||
src[i + 4] = _data[i*4 + 1];
|
|
||||||
src[i + 8] = _data[i*4 + 2];
|
|
||||||
src[i + 12] = _data[i*4 + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate pairs for first 8 elements (cofactors)
|
|
||||||
tmp[0] = src[10] * src[15];
|
|
||||||
tmp[1] = src[11] * src[14];
|
|
||||||
tmp[2] = src[9] * src[15];
|
|
||||||
tmp[3] = src[11] * src[13];
|
|
||||||
tmp[4] = src[9] * src[14];
|
|
||||||
tmp[5] = src[10] * src[13];
|
|
||||||
tmp[6] = src[8] * src[15];
|
|
||||||
tmp[7] = src[11] * src[12];
|
|
||||||
tmp[8] = src[8] * src[14];
|
|
||||||
tmp[9] = src[10] * src[12];
|
|
||||||
tmp[10] = src[8] * src[13];
|
|
||||||
tmp[11] = src[9] * src[12];
|
|
||||||
|
|
||||||
// calculate first 8 elements (cofactors)
|
|
||||||
dst._data[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
|
|
||||||
dst._data[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
|
|
||||||
dst._data[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
|
|
||||||
dst._data[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
|
|
||||||
dst._data[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
|
|
||||||
dst._data[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
|
|
||||||
dst._data[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
|
|
||||||
dst._data[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
|
|
||||||
dst._data[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
|
|
||||||
dst._data[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
|
|
||||||
dst._data[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
|
|
||||||
dst._data[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
|
|
||||||
dst._data[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
|
|
||||||
dst._data[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
|
|
||||||
dst._data[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
|
|
||||||
dst._data[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
|
|
||||||
|
|
||||||
// calculate pairs for second 8 elements (cofactors)
|
|
||||||
tmp[0] = src[2]*src[7];
|
|
||||||
tmp[1] = src[3]*src[6];
|
|
||||||
tmp[2] = src[1]*src[7];
|
|
||||||
tmp[3] = src[3]*src[5];
|
|
||||||
tmp[4] = src[1]*src[6];
|
|
||||||
tmp[5] = src[2]*src[5];
|
|
||||||
tmp[6] = src[0]*src[7];
|
|
||||||
tmp[7] = src[3]*src[4];
|
|
||||||
tmp[8] = src[0]*src[6];
|
|
||||||
tmp[9] = src[2]*src[4];
|
|
||||||
tmp[10] = src[0]*src[5];
|
|
||||||
tmp[11] = src[1]*src[4];
|
|
||||||
|
|
||||||
// calculate second 8 elements (cofactors)
|
|
||||||
dst._data[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
|
|
||||||
dst._data[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
|
|
||||||
dst._data[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
|
|
||||||
dst._data[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
|
|
||||||
dst._data[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
|
|
||||||
dst._data[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
|
|
||||||
dst._data[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
|
|
||||||
dst._data[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
|
|
||||||
dst._data[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
|
|
||||||
dst._data[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
|
|
||||||
dst._data[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
|
|
||||||
dst._data[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
|
|
||||||
dst._data[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
|
|
||||||
dst._data[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
|
|
||||||
dst._data[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
|
|
||||||
dst._data[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
|
|
||||||
|
|
||||||
// calculate matrix inverse
|
|
||||||
det=src[0]*dst._data[0]+src[1]*dst._data[1]+src[2]*dst._data[2]+src[3]*dst._data[3];
|
|
||||||
det = 1/det;
|
|
||||||
for ( int j = 0; j < 16; j++) {
|
|
||||||
dst._data[j] *= det;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::Rotate(const CQuaternion& quat)
|
|
||||||
{
|
|
||||||
CMatrix3D rotationMatrix=quat.ToMatrix();
|
|
||||||
(*this) = rotationMatrix * (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMatrix3D::SetRotation(const CQuaternion& quat)
|
|
||||||
{
|
|
||||||
quat.ToMatrix(*this);
|
|
||||||
}
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
|||||||
#ifndef __MATRIX3D_H
|
|
||||||
#define __MATRIX3D_H
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Vector4D.h"
|
|
||||||
|
|
||||||
class CQuaternion;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
|
||||||
// CMatrix3D: a 4x4 matrix class for common operations in 3D
|
|
||||||
class CMatrix3D
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// the matrix data itself - accessible as either longhand names
|
|
||||||
// or via a flat array
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
float _11, _21, _31, _41;
|
|
||||||
float _12, _22, _32, _42;
|
|
||||||
float _13, _23, _33, _43;
|
|
||||||
float _14, _24, _34, _44;
|
|
||||||
};
|
|
||||||
float _data[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructors
|
|
||||||
CMatrix3D();
|
|
||||||
CMatrix3D(float a11,float a12,float a13,float a14,float a21,float a22,float a23,float a24,
|
|
||||||
float a31,float a32,float a33,float a34,float a41,float a42,float a43,float a44);
|
|
||||||
|
|
||||||
// accessors to individual elements of matrix
|
|
||||||
float& operator()(int col,int row) {
|
|
||||||
return _data[row*4+col];
|
|
||||||
}
|
|
||||||
const float& operator()(int col,int row) const {
|
|
||||||
return _data[row*4+col];
|
|
||||||
}
|
|
||||||
|
|
||||||
// matrix multiplication
|
|
||||||
CMatrix3D operator*(const CMatrix3D &matrix) const;
|
|
||||||
// matrix multiplication/assignment
|
|
||||||
CMatrix3D& operator*=(const CMatrix3D &matrix);
|
|
||||||
// matrix scaling
|
|
||||||
CMatrix3D operator*(float f) const;
|
|
||||||
// matrix scaling/assignment
|
|
||||||
CMatrix3D& operator*=(float f);
|
|
||||||
// matrix addition
|
|
||||||
CMatrix3D operator+(const CMatrix3D &matrix) const;
|
|
||||||
// matrix addition/assignment
|
|
||||||
CMatrix3D& operator+=(const CMatrix3D &matrix);
|
|
||||||
|
|
||||||
// set this matrix to the identity matrix
|
|
||||||
void SetIdentity();
|
|
||||||
// set this matrix to the zero matrix
|
|
||||||
void SetZero();
|
|
||||||
|
|
||||||
// set this matrix to a rotation matrix for a rotation about X axis of given angle
|
|
||||||
void SetXRotation(float angle);
|
|
||||||
// set this matrix to a rotation matrix for a rotation about Y axis of given angle
|
|
||||||
void SetYRotation(float angle);
|
|
||||||
// set this matrix to a rotation matrix for a rotation about Z axis of given angle
|
|
||||||
void SetZRotation(float angle);
|
|
||||||
// set this matrix to a rotation described by given quaternion
|
|
||||||
void SetRotation(const CQuaternion& quat);
|
|
||||||
|
|
||||||
// concatentate a rotation about the X axis onto this matrix
|
|
||||||
void RotateX(float angle);
|
|
||||||
// concatentate a rotation about the Y axis onto this matrix
|
|
||||||
void RotateY(float angle);
|
|
||||||
// concatentate a rotation about the Z axis onto this matrix
|
|
||||||
void RotateZ(float angle);
|
|
||||||
// concatentate a rotation described by given quaternion
|
|
||||||
void Rotate(const CQuaternion& quat);
|
|
||||||
|
|
||||||
// set this matrix to given translation
|
|
||||||
void SetTranslation(float x, float y, float z);
|
|
||||||
void SetTranslation(const CVector3D& vector);
|
|
||||||
|
|
||||||
// concatenate given translation onto this matrix
|
|
||||||
void Translate(float x, float y, float z);
|
|
||||||
void Translate(const CVector3D& vector);
|
|
||||||
|
|
||||||
// set this matrix to the given scaling matrix
|
|
||||||
void SetScaling(float x_scale, float y_scale, float z_scale);
|
|
||||||
|
|
||||||
// concatentate given scaling matrix onto this matrix
|
|
||||||
void Scale(float x_scale, float y_scale, float z_scale);
|
|
||||||
|
|
||||||
// calculate the inverse of this matrix, store in dst
|
|
||||||
void GetInverse(CMatrix3D& dst) const;
|
|
||||||
|
|
||||||
// calculate the transpose of this matrix, store in dst
|
|
||||||
void GetTranspose(CMatrix3D& dst) const;
|
|
||||||
|
|
||||||
// return the translation component of this matrix
|
|
||||||
CVector3D GetTranslation() const;
|
|
||||||
// return left vector, derived from rotation
|
|
||||||
CVector3D GetLeft() const;
|
|
||||||
// return up vector, derived from rotation
|
|
||||||
CVector3D GetUp() const;
|
|
||||||
// return forward vector, derived from rotation
|
|
||||||
CVector3D GetIn() const;
|
|
||||||
|
|
||||||
// transform a 3D vector by this matrix
|
|
||||||
void Transform(const CVector3D &vector,CVector3D& result) const;
|
|
||||||
CVector3D Transform(const CVector3D &vector) const;
|
|
||||||
// transform a 4D vector by this matrix
|
|
||||||
void Transform(const CVector4D &vector,CVector4D& result) const;
|
|
||||||
CVector4D Transform(const CVector4D &vector) const;
|
|
||||||
// rotate a vector by this matrix
|
|
||||||
void Rotate(const CVector3D& vector,CVector3D& result) const;
|
|
||||||
CVector3D Rotate(const CVector3D& vector) const;
|
|
||||||
// rotate a vector by the transpose of this matrix
|
|
||||||
void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
|
|
||||||
CVector3D RotateTransposed(const CVector3D& vector) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,34 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: MiniPatch.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "MiniPatch.h"
|
|
||||||
#include "Patch.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
CMiniPatch::CMiniPatch() : Tex1(0), Tex1Priority(0), m_Parent(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Destructor
|
|
||||||
CMiniPatch::~CMiniPatch()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GetTileIndex: get the index of this tile in the root terrain object;
|
|
||||||
// on return, parameters x,y contain index in [0,MapSize)
|
|
||||||
void CMiniPatch::GetTileIndex(u32& x,u32& z)
|
|
||||||
{
|
|
||||||
uintptr_t tindex=this-&m_Parent->m_MiniPatches[0][0];
|
|
||||||
x=(m_Parent->m_X*16)+tindex%16;
|
|
||||||
z=(m_Parent->m_Z*16)+tindex/16;
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: MiniPatch.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _MINIPATCH_H
|
|
||||||
#define _MINIPATCH_H
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
|
|
||||||
class CPatch;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CMiniPatch: definition of a single terrain tile
|
|
||||||
class CMiniPatch
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CMiniPatch();
|
|
||||||
// destructor
|
|
||||||
~CMiniPatch();
|
|
||||||
|
|
||||||
// get the index of this tile in the root terrain object; x,y in [0,MapSize)
|
|
||||||
void GetTileIndex(u32& x,u32& z);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// texture applied to tile
|
|
||||||
Handle Tex1;
|
|
||||||
// 'priority' of the texture - determines drawing order of terrain textures
|
|
||||||
int Tex1Priority;
|
|
||||||
// parent patch
|
|
||||||
CPatch* m_Parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,169 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Model.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "Model.h"
|
|
||||||
#include "Quaternion.h"
|
|
||||||
#include "Bound.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
CModel::CModel()
|
|
||||||
: m_pModelDef(0), m_Anim(0), m_AnimTime(0),
|
|
||||||
m_BoneMatrices(0), m_InvBoneMatrices(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Destructor
|
|
||||||
CModel::~CModel()
|
|
||||||
{
|
|
||||||
ReleaseData();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ReleaseData: delete anything allocated by the model
|
|
||||||
void CModel::ReleaseData()
|
|
||||||
{
|
|
||||||
delete[] m_BoneMatrices;
|
|
||||||
delete[] m_InvBoneMatrices;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// InitModel: setup model from given geometry
|
|
||||||
bool CModel::InitModel(CModelDef* modeldef)
|
|
||||||
{
|
|
||||||
// clean up any existing data first
|
|
||||||
ReleaseData();
|
|
||||||
|
|
||||||
m_pModelDef = modeldef;
|
|
||||||
|
|
||||||
u32 numBones=modeldef->GetNumBones();
|
|
||||||
if (numBones>0) {
|
|
||||||
// allocate matrices for bone transformations
|
|
||||||
m_BoneMatrices=new CMatrix3D[numBones];
|
|
||||||
m_InvBoneMatrices=new CMatrix3D[numBones];
|
|
||||||
// store default pose until animation assigned
|
|
||||||
CBoneState* defpose=modeldef->GetBones();
|
|
||||||
for (uint i=0;i<numBones;i++) {
|
|
||||||
CMatrix3D& m=m_BoneMatrices[i];
|
|
||||||
m.SetIdentity();
|
|
||||||
m.Rotate(defpose[i].m_Rotation);
|
|
||||||
m.Translate(defpose[i].m_Translation);
|
|
||||||
m.GetInverse(m_InvBoneMatrices[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SkinPoint: skin the given point using the given blend and bonestate data
|
|
||||||
static CVector3D SkinPoint(const CVector3D& pos,const SVertexBlend& blend,
|
|
||||||
const CBoneState* bonestates)
|
|
||||||
{
|
|
||||||
CVector3D result(0,0,0);
|
|
||||||
for (int i=0;i<SVertexBlend::SIZE && blend.m_Bone[i]!=0xff;i++) {
|
|
||||||
CMatrix3D m;
|
|
||||||
m.SetIdentity();
|
|
||||||
m.Rotate(bonestates[blend.m_Bone[i]].m_Rotation);
|
|
||||||
m.Translate(bonestates[blend.m_Bone[i]].m_Translation);
|
|
||||||
|
|
||||||
CVector3D tmp=m.Transform(pos);
|
|
||||||
result+=tmp*blend.m_Weight[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CalcBound: calculate the world space bounds of this model
|
|
||||||
//
|
|
||||||
// TODO,RC 11/03/04: need to calculate (and store somewhere) the object space
|
|
||||||
// bounds, and then just retransform the bounds as necessary, rather than
|
|
||||||
// recalculating them from vertex data every time the transform changes
|
|
||||||
void CModel::CalcBounds()
|
|
||||||
{
|
|
||||||
m_Bounds.SetEmpty();
|
|
||||||
|
|
||||||
int numverts=m_pModelDef->GetNumVertices();
|
|
||||||
SModelVertex* verts=m_pModelDef->GetVertices();
|
|
||||||
|
|
||||||
u32 numbones=m_pModelDef->GetNumBones();
|
|
||||||
if (numbones>0) {
|
|
||||||
// Boned object: tricky to get an ideal bound - for the minute, just use the bound of
|
|
||||||
// the reference pose. There's no guarantee that when animations are applied to the
|
|
||||||
// model, the bounds will be within this bound - ideally, we want the bound of the
|
|
||||||
// object to be the union of the bounds of the model for each animation
|
|
||||||
for (int i=0;i<numverts;i++) {
|
|
||||||
CVector3D tmp=SkinPoint(verts[i].m_Coords,verts[i].m_Blend,m_pModelDef->GetBones());
|
|
||||||
m_Bounds+=m_Transform.Transform(tmp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i=0;i<numverts;i++) {
|
|
||||||
m_Bounds+=m_Transform.Transform(verts[i].m_Coords);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Update: update this model by the given time, in seconds
|
|
||||||
void CModel::Update(float time)
|
|
||||||
{
|
|
||||||
// convert to ms
|
|
||||||
time*=1000;
|
|
||||||
|
|
||||||
if (m_Anim && m_BoneMatrices) {
|
|
||||||
m_AnimTime+=time;
|
|
||||||
|
|
||||||
float duration=m_Anim->GetDuration();
|
|
||||||
if (m_AnimTime>duration) {
|
|
||||||
m_AnimTime=(float) fmod(m_AnimTime,duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Anim->BuildBoneMatrices(m_AnimTime,m_BoneMatrices);
|
|
||||||
for (int i=0;i<m_pModelDef->GetNumBones();i++) {
|
|
||||||
m_BoneMatrices[i].GetInverse(m_InvBoneMatrices[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_RenderData) m_RenderData->m_UpdateFlags|=RENDERDATA_UPDATE_VERTICES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SetAnimation: set the given animation as the current animation on this model;
|
|
||||||
// return false on error, else true
|
|
||||||
bool CModel::SetAnimation(CSkeletonAnim* anim)
|
|
||||||
{
|
|
||||||
if (anim) {
|
|
||||||
if (!m_BoneMatrices) {
|
|
||||||
// not boned, can't animate
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (anim->GetNumKeys()!=m_pModelDef->GetNumBones()) {
|
|
||||||
// mismatch between models skeleton and animations skeleton
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_AnimTime=0;
|
|
||||||
m_Anim=anim;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Clone: return a clone of this model
|
|
||||||
CModel* CModel::Clone() const
|
|
||||||
{
|
|
||||||
CModel* clone=new CModel;
|
|
||||||
clone->InitModel(m_pModelDef);
|
|
||||||
clone->SetTexture(m_Texture);
|
|
||||||
clone->SetAnimation(m_Anim);
|
|
||||||
return clone;
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Model.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _MODEL_H
|
|
||||||
#define _MODEL_H
|
|
||||||
|
|
||||||
#include "Texture.h"
|
|
||||||
#include "ModelDef.h"
|
|
||||||
#include "RenderableObject.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CModel: basically, a mesh object - holds the texturing and skinning
|
|
||||||
// information for a model in game
|
|
||||||
class CModel : public CRenderableObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CModel();
|
|
||||||
// destructor
|
|
||||||
~CModel();
|
|
||||||
|
|
||||||
// setup model from given geometry
|
|
||||||
bool InitModel(CModelDef *modeldef);
|
|
||||||
// calculate the world space bounds of this model
|
|
||||||
void CalcBounds();
|
|
||||||
// update this model's state; 'time' is the time since the last update, in MS
|
|
||||||
void Update(float time);
|
|
||||||
|
|
||||||
// get the model's geometry data
|
|
||||||
CModelDef *GetModelDef() { return m_pModelDef; }
|
|
||||||
|
|
||||||
// set the model's texture
|
|
||||||
void SetTexture(const CTexture& tex) { m_Texture=tex; }
|
|
||||||
// get the model's texture
|
|
||||||
CTexture* GetTexture() { return &m_Texture; }
|
|
||||||
|
|
||||||
// set the given animation as the current animation on this model
|
|
||||||
bool SetAnimation(CSkeletonAnim* anim);
|
|
||||||
// get the currently playing animation, if any
|
|
||||||
CSkeletonAnim* GetAnimation() { return m_Anim; }
|
|
||||||
|
|
||||||
// return the models bone matrices
|
|
||||||
const CMatrix3D* GetBoneMatrices() { return m_BoneMatrices; }
|
|
||||||
// return the models inverted bone matrices
|
|
||||||
const CMatrix3D* GetInvBoneMatrices() { return m_InvBoneMatrices; }
|
|
||||||
|
|
||||||
// return a clone of this model
|
|
||||||
CModel* Clone() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// delete anything allocated by the model
|
|
||||||
void ReleaseData();
|
|
||||||
|
|
||||||
// texture used by model
|
|
||||||
CTexture m_Texture;
|
|
||||||
// pointer to the model's raw 3d data
|
|
||||||
CModelDef* m_pModelDef;
|
|
||||||
// animation currently playing on this model, if any
|
|
||||||
CSkeletonAnim* m_Anim;
|
|
||||||
// time (in MS) into the current animation
|
|
||||||
float m_AnimTime;
|
|
||||||
// current state of all bones on this model; null if associated modeldef isn't skeletal
|
|
||||||
CMatrix3D* m_BoneMatrices;
|
|
||||||
// inverse of all the above matrices
|
|
||||||
CMatrix3D* m_InvBoneMatrices;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,90 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: ModelDef.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "ModelDef.h"
|
|
||||||
#include "FilePacker.h"
|
|
||||||
#include "FileUnpacker.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CModelDef Constructor
|
|
||||||
CModelDef::CModelDef()
|
|
||||||
: m_pVertices(0), m_NumVertices(0), m_pFaces(0), m_NumFaces(0), m_Bones(0), m_NumBones(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CModelDef Destructor
|
|
||||||
CModelDef::~CModelDef()
|
|
||||||
{
|
|
||||||
delete[] m_pVertices;
|
|
||||||
delete[] m_pFaces;
|
|
||||||
delete[] m_Bones;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Load: read and return a new CModelDef initialised with data from given file
|
|
||||||
CModelDef* CModelDef::Load(const char* filename)
|
|
||||||
{
|
|
||||||
CFileUnpacker unpacker;
|
|
||||||
|
|
||||||
// read everything in from file
|
|
||||||
unpacker.Read(filename,"PSMD");
|
|
||||||
|
|
||||||
// check version
|
|
||||||
if (unpacker.GetVersion()<FILE_READ_VERSION) {
|
|
||||||
throw CFileUnpacker::CFileVersionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
CModelDef* mdef=new CModelDef;
|
|
||||||
try {
|
|
||||||
// now unpack everything
|
|
||||||
unpacker.UnpackRaw(&mdef->m_NumVertices,sizeof(mdef->m_NumVertices));
|
|
||||||
mdef->m_pVertices=new SModelVertex[mdef->m_NumVertices];
|
|
||||||
unpacker.UnpackRaw(mdef->m_pVertices,sizeof(SModelVertex)*mdef->m_NumVertices);
|
|
||||||
|
|
||||||
unpacker.UnpackRaw(&mdef->m_NumFaces,sizeof(mdef->m_NumFaces));
|
|
||||||
mdef->m_pFaces=new SModelFace[mdef->m_NumFaces];
|
|
||||||
unpacker.UnpackRaw(mdef->m_pFaces,sizeof(SModelFace)*mdef->m_NumFaces);
|
|
||||||
|
|
||||||
unpacker.UnpackRaw(&mdef->m_NumBones,sizeof(mdef->m_NumBones));
|
|
||||||
if (mdef->m_NumBones) {
|
|
||||||
mdef->m_Bones=new CBoneState[mdef->m_NumBones];
|
|
||||||
unpacker.UnpackRaw(mdef->m_Bones,mdef->m_NumBones*sizeof(CBoneState));
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
delete mdef;
|
|
||||||
throw CFileUnpacker::CFileEOFError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return mdef;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Save: write the given CModelDef to the given file
|
|
||||||
void CModelDef::Save(const char* filename,const CModelDef* mdef)
|
|
||||||
{
|
|
||||||
CFilePacker packer;
|
|
||||||
|
|
||||||
// pack everything up
|
|
||||||
u32 numVertices=mdef->GetNumVertices();
|
|
||||||
packer.PackRaw(&numVertices,sizeof(numVertices));
|
|
||||||
packer.PackRaw(mdef->GetVertices(),sizeof(SModelVertex)*numVertices);
|
|
||||||
|
|
||||||
u32 numFaces=mdef->GetNumFaces();
|
|
||||||
packer.PackRaw(&numFaces,sizeof(numFaces));
|
|
||||||
packer.PackRaw(mdef->GetFaces(),sizeof(SModelFace)*numFaces);
|
|
||||||
|
|
||||||
packer.PackRaw(&mdef->m_NumBones,sizeof(mdef->m_NumBones));
|
|
||||||
if (mdef->m_NumBones) {
|
|
||||||
packer.PackRaw(mdef->m_Bones,sizeof(CBoneState)*mdef->m_NumBones);
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush everything out to file
|
|
||||||
packer.Write(filename,FILE_VERSION,"PSMD");
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: ModelDef.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _MODELDEF_H
|
|
||||||
#define _MODELDEF_H
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// TODO,RC 11/03/04: get rid of all the m_Name[MAX_NAME_LENGTH] - use CStr
|
|
||||||
// - problem: conflicts with CStr in MAX's SDK; can't compile PMDExp if
|
|
||||||
// ps\CStr.h included here
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "SkeletonAnim.h"
|
|
||||||
|
|
||||||
#ifndef MAX_NAME_LENGTH
|
|
||||||
#define MAX_NAME_LENGTH (128)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SVertexBlend: structure containing the necessary data for blending vertices
|
|
||||||
// with multiple bones
|
|
||||||
struct SVertexBlend
|
|
||||||
{
|
|
||||||
enum { SIZE = 4 };
|
|
||||||
// index of the influencing bone, or 0xff if none
|
|
||||||
u8 m_Bone[SIZE];
|
|
||||||
// weight of the influence; all weights sum to 1
|
|
||||||
float m_Weight[SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SModelVertex: structure containing per-vertex data
|
|
||||||
struct SModelVertex
|
|
||||||
{
|
|
||||||
// vertex position
|
|
||||||
CVector3D m_Coords;
|
|
||||||
// vertex normal
|
|
||||||
CVector3D m_Norm;
|
|
||||||
// vertex UVs
|
|
||||||
float m_U, m_V;
|
|
||||||
// vertex blend data
|
|
||||||
SVertexBlend m_Blend;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SModelFace: structure containing per-face data
|
|
||||||
struct SModelFace
|
|
||||||
{
|
|
||||||
// indices of the 3 vertices on this face
|
|
||||||
u16 m_Verts[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CModelDef: a raw 3D model; describes the vertices, faces, skinning and skeletal
|
|
||||||
// information of a model
|
|
||||||
class CModelDef
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// current file version given to saved animations
|
|
||||||
enum { FILE_VERSION = 1 };
|
|
||||||
// supported file read version - files with a version less than this will be rejected
|
|
||||||
enum { FILE_READ_VERSION = 1 };
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CModelDef();
|
|
||||||
// destructor
|
|
||||||
virtual ~CModelDef();
|
|
||||||
|
|
||||||
// model I/O functions
|
|
||||||
static CModelDef* Load(const char* filename);
|
|
||||||
static void Save(const char* filename,const CModelDef* mdef);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// accessor: get vertex data
|
|
||||||
int GetNumVertices() const { return m_NumVertices; }
|
|
||||||
SModelVertex *GetVertices() const { return m_pVertices; }
|
|
||||||
|
|
||||||
// accessor: get face data
|
|
||||||
int GetNumFaces() const { return m_NumFaces; }
|
|
||||||
SModelFace *GetFaces() const { return m_pFaces; }
|
|
||||||
|
|
||||||
// accessor: get bone data
|
|
||||||
int GetNumBones() const { return m_NumBones; }
|
|
||||||
CBoneState *GetBones() const { return m_Bones; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
// vertex data
|
|
||||||
u32 m_NumVertices;
|
|
||||||
SModelVertex* m_pVertices;
|
|
||||||
// face data
|
|
||||||
u32 m_NumFaces;
|
|
||||||
SModelFace* m_pFaces;
|
|
||||||
// bone data - default model pose
|
|
||||||
u32 m_NumBones;
|
|
||||||
CBoneState* m_Bones;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,257 +0,0 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "res/tex.h"
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "TransparencyRenderer.h"
|
|
||||||
#include "ModelRData.h"
|
|
||||||
#include "terrain/Model.h"
|
|
||||||
|
|
||||||
|
|
||||||
CModelRData::CModelRData(CModel* model) : m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0)
|
|
||||||
{
|
|
||||||
assert(model);
|
|
||||||
// build all data now
|
|
||||||
Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
CModelRData::~CModelRData()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModelRData::Build()
|
|
||||||
{
|
|
||||||
BuildVertices();
|
|
||||||
BuildIndices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModelRData::BuildIndices()
|
|
||||||
{
|
|
||||||
CModelDef* mdef=m_Model->GetModelDef();
|
|
||||||
|
|
||||||
// allocate indices if we haven't got any already
|
|
||||||
if (!m_Indices) {
|
|
||||||
m_Indices=new u16[mdef->GetNumFaces()*3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// build indices
|
|
||||||
u32 indices=0;
|
|
||||||
SModelFace* faces=mdef->GetFaces();
|
|
||||||
for (int j=0; j<mdef->GetNumFaces(); j++) {
|
|
||||||
SModelFace& face=faces[j];
|
|
||||||
m_Indices[indices++]=face.m_Verts[0];
|
|
||||||
m_Indices[indices++]=face.m_Verts[1];
|
|
||||||
m_Indices[indices++]=face.m_Verts[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int clamp(int x,int min,int max)
|
|
||||||
{
|
|
||||||
if (x<min) return min;
|
|
||||||
else if (x>max) return max;
|
|
||||||
else return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SColor4ub ConvertColor(const RGBColor& src)
|
|
||||||
{
|
|
||||||
SColor4ub result;
|
|
||||||
result.R=clamp(int(src.X*255),0,255);
|
|
||||||
result.G=clamp(int(src.Y*255),0,255);
|
|
||||||
result.B=clamp(int(src.Z*255),0,255);
|
|
||||||
result.A=0xff;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CVector3D SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices)
|
|
||||||
{
|
|
||||||
CVector3D result(0,0,0),tmp;
|
|
||||||
|
|
||||||
for (u32 i=0;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
|
||||||
const CMatrix3D& m=matrices[vertex.m_Blend.m_Bone[i]];
|
|
||||||
m.Transform(vertex.m_Coords,tmp);
|
|
||||||
result+=tmp*vertex.m_Blend.m_Weight[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CVector3D SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices)
|
|
||||||
{
|
|
||||||
CVector3D result(0,0,0),tmp;
|
|
||||||
|
|
||||||
for (u32 i=0;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
|
||||||
const CMatrix3D& m=invmatrices[vertex.m_Blend.m_Bone[i]];
|
|
||||||
m.RotateTransposed(vertex.m_Norm,tmp);
|
|
||||||
result+=tmp*vertex.m_Blend.m_Weight[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CModelRData::BuildVertices()
|
|
||||||
{
|
|
||||||
CModelDef* mdef=m_Model->GetModelDef();
|
|
||||||
|
|
||||||
// allocate vertices if we haven't got any already
|
|
||||||
if (!m_Vertices) {
|
|
||||||
m_Vertices=new SVertex[mdef->GetNumVertices()];
|
|
||||||
m_Normals=new CVector3D[mdef->GetNumVertices()];
|
|
||||||
}
|
|
||||||
|
|
||||||
// build vertices
|
|
||||||
u32 numVertices=mdef->GetNumVertices();
|
|
||||||
SModelVertex* vertices=mdef->GetVertices();
|
|
||||||
if (m_Model->GetBoneMatrices()) {
|
|
||||||
// boned model - calculate skinned vertex positions/normals
|
|
||||||
for (uint j=0; j<numVertices; j++) {
|
|
||||||
m_Vertices[j].m_Position=SkinPoint(vertices[j],m_Model->GetBoneMatrices());
|
|
||||||
m_Normals[j]=SkinNormal(vertices[j],m_Model->GetInvBoneMatrices());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// just copy regular positions
|
|
||||||
for (uint j=0; j<numVertices; j++) {
|
|
||||||
m_Vertices[j].m_Position=vertices[j].m_Coords;
|
|
||||||
m_Normals[j]=vertices[j].m_Norm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now fill in UV and vertex colour data
|
|
||||||
for (uint j=0; j<numVertices; j++) {
|
|
||||||
m_Vertices[j].m_UVs[0]=vertices[j].m_U;
|
|
||||||
m_Vertices[j].m_UVs[1]=1-vertices[j].m_V;
|
|
||||||
|
|
||||||
RGBColor c;
|
|
||||||
g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j],c);
|
|
||||||
|
|
||||||
m_Vertices[j].m_Color=ConvertColor(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
if (!m_VB) {
|
|
||||||
glGenBuffersARB(1,(GLuint*) &m_VB);
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
|
||||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,mdef->GetNumVertices()*sizeof(SVertex),0,mdef->GetNumBones() ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB);
|
|
||||||
}
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
|
||||||
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,0,mdef->GetNumVertices()*sizeof(SVertex),m_Vertices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CModelRData::RenderStreams(u32 streamflags,const CMatrix3D& transform,bool transparentPass)
|
|
||||||
{
|
|
||||||
// ignore transparent passes
|
|
||||||
if (!transparentPass && g_Renderer.IsTextureTransparent(m_Model->GetTexture())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef();
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
|
|
||||||
CMatrix3D tmp;
|
|
||||||
glMultMatrixf(&transform._11);
|
|
||||||
|
|
||||||
if (streamflags & STREAM_UV0) g_Renderer.SetTexture(0,m_Model->GetTexture(),GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
u8* base;
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
|
||||||
base=0;
|
|
||||||
} else {
|
|
||||||
base=(u8*) &m_Vertices[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// set vertex pointers
|
|
||||||
u32 stride=sizeof(SVertex);
|
|
||||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position));
|
|
||||||
if (streamflags & STREAM_COLOR) glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SVertex,m_Color));
|
|
||||||
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs));
|
|
||||||
|
|
||||||
// render the lot
|
|
||||||
u32 numFaces=mdldef->GetNumFaces();
|
|
||||||
glDrawElements(GL_TRIANGLES,numFaces*3,GL_UNSIGNED_SHORT,m_Indices);
|
|
||||||
|
|
||||||
// bump stats
|
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
|
||||||
if (transparentPass) {
|
|
||||||
g_Renderer.m_Stats.m_TransparentTris+=numFaces;
|
|
||||||
} else {
|
|
||||||
g_Renderer.m_Stats.m_ModelTris+=numFaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CModelRData::Update()
|
|
||||||
{
|
|
||||||
if (m_UpdateFlags!=0) {
|
|
||||||
// renderdata changed : rebuild necessary portions
|
|
||||||
if (m_UpdateFlags & RENDERDATA_UPDATE_VERTICES) {
|
|
||||||
BuildVertices();
|
|
||||||
}
|
|
||||||
if (m_UpdateFlags & RENDERDATA_UPDATE_INDICES) {
|
|
||||||
BuildIndices();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_UpdateFlags=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::pair<int,float> IntFloatPair;
|
|
||||||
static std::vector<IntFloatPair> IndexSorter;
|
|
||||||
|
|
||||||
struct SortFacesByDist {
|
|
||||||
bool operator()(const IntFloatPair& lhs,const IntFloatPair& rhs) {
|
|
||||||
return lhs.second>rhs.second ? true : false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
float CModelRData::BackToFrontIndexSort(CMatrix3D& objToCam)
|
|
||||||
{
|
|
||||||
float mindist=1.0e30f;
|
|
||||||
CVector3D osvtx,csvtx;
|
|
||||||
|
|
||||||
CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef();
|
|
||||||
|
|
||||||
SModelVertex* vtxs=mdldef->GetVertices();
|
|
||||||
|
|
||||||
u32 numFaces=mdldef->GetNumFaces();
|
|
||||||
SModelFace* faces=mdldef->GetFaces();
|
|
||||||
|
|
||||||
IndexSorter.reserve(numFaces);
|
|
||||||
|
|
||||||
SModelFace* facePtr=faces;
|
|
||||||
u32 i;
|
|
||||||
for (i=0;i<numFaces;i++)
|
|
||||||
{
|
|
||||||
osvtx=vtxs[facePtr->m_Verts[0]].m_Coords;
|
|
||||||
osvtx+=vtxs[facePtr->m_Verts[1]].m_Coords;
|
|
||||||
osvtx+=vtxs[facePtr->m_Verts[2]].m_Coords;
|
|
||||||
osvtx*=1.0f/3.0f;
|
|
||||||
|
|
||||||
csvtx=objToCam.Transform(osvtx);
|
|
||||||
float distsqrd=SQR(csvtx.X)+SQR(csvtx.Y)+SQR(csvtx.Z);
|
|
||||||
if (distsqrd<mindist) mindist=distsqrd;
|
|
||||||
|
|
||||||
IndexSorter.push_back(IntFloatPair(i,distsqrd));
|
|
||||||
facePtr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(IndexSorter.begin(),IndexSorter.end(),SortFacesByDist());
|
|
||||||
|
|
||||||
// now build index list
|
|
||||||
u32 indices=0;
|
|
||||||
for (i=0;i<numFaces;i++) {
|
|
||||||
SModelFace& face=faces[IndexSorter[i].first];
|
|
||||||
m_Indices[indices++]=face.m_Verts[0];
|
|
||||||
m_Indices[indices++]=face.m_Verts[1];
|
|
||||||
m_Indices[indices++]=face.m_Verts[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear list for next call
|
|
||||||
IndexSorter.clear();
|
|
||||||
|
|
||||||
return mindist;
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
#ifndef _MODELRDATA_H
|
|
||||||
#define _MODELRDATA_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "RenderableObject.h"
|
|
||||||
|
|
||||||
class CModel;
|
|
||||||
|
|
||||||
class CModelRData : public CRenderData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CModelRData(CModel* model);
|
|
||||||
~CModelRData();
|
|
||||||
|
|
||||||
void Update();
|
|
||||||
void RenderStreams(u32 streamflags,const CMatrix3D& transform,bool transparentPass=false);
|
|
||||||
|
|
||||||
// sort indices of this object from back to front according to given
|
|
||||||
// object to camera space transform; return sqrd distance to centre of nearest triangle
|
|
||||||
float BackToFrontIndexSort(CMatrix3D& objToCam);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// build this renderdata object
|
|
||||||
void Build();
|
|
||||||
|
|
||||||
void BuildVertices();
|
|
||||||
void BuildIndices();
|
|
||||||
|
|
||||||
|
|
||||||
struct SVertex {
|
|
||||||
// vertex position
|
|
||||||
CVector3D m_Position;
|
|
||||||
// vertex uvs for base texture
|
|
||||||
float m_UVs[2];
|
|
||||||
// vertex color
|
|
||||||
SColor4ub m_Color;
|
|
||||||
};
|
|
||||||
|
|
||||||
// owner model
|
|
||||||
CModel* m_Model;
|
|
||||||
// handle to models vertex buffer
|
|
||||||
u32 m_VB;
|
|
||||||
// model render vertices
|
|
||||||
SVertex* m_Vertices;
|
|
||||||
// transformed vertex normals - required for recalculating lighting on skinned models
|
|
||||||
CVector3D* m_Normals;
|
|
||||||
// model render indices
|
|
||||||
u16* m_Indices;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,236 +0,0 @@
|
|||||||
#include "ObjectEntry.h"
|
|
||||||
#include "ObjectManager.h"
|
|
||||||
#include "terrain/Model.h"
|
|
||||||
#include "terrain/ModelDef.h"
|
|
||||||
|
|
||||||
#include "UnitManager.h"
|
|
||||||
|
|
||||||
// xerces XML stuff
|
|
||||||
#include <xercesc/dom/DOM.hpp>
|
|
||||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
|
||||||
#include <xercesc/framework/LocalFileInputSource.hpp>
|
|
||||||
#include <xercesc/util/XMLString.hpp>
|
|
||||||
#include <xercesc/util/PlatformUtils.hpp>
|
|
||||||
|
|
||||||
// Gee's custom error handler
|
|
||||||
#include <ps/XercesErrorHandler.h>
|
|
||||||
|
|
||||||
// automatically use namespace ..
|
|
||||||
XERCES_CPP_NAMESPACE_USE
|
|
||||||
|
|
||||||
|
|
||||||
CObjectEntry::CObjectEntry(int type) : m_Model(0), m_Type(type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CObjectEntry::~CObjectEntry()
|
|
||||||
{
|
|
||||||
delete m_Model;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CObjectEntry::BuildModel()
|
|
||||||
{
|
|
||||||
// check we've enough data to consider building the object
|
|
||||||
if (m_ModelName.Length()==0 || m_TextureName.Length()==0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the root directory of this object
|
|
||||||
CStr dirname=g_ObjMan.m_ObjectTypes[m_Type].m_Name;
|
|
||||||
|
|
||||||
// remember the old model so we can replace any models using it later on
|
|
||||||
CModelDef* oldmodel=m_Model ? m_Model->GetModelDef() : 0;
|
|
||||||
|
|
||||||
// build filename
|
|
||||||
CStr modelfilename("mods\\official\\");
|
|
||||||
modelfilename+=m_ModelName;
|
|
||||||
|
|
||||||
// try and create a model
|
|
||||||
CModelDef* modeldef;
|
|
||||||
|
|
||||||
try {
|
|
||||||
modeldef=CModelDef::Load((const char*) modelfilename);
|
|
||||||
} catch (...) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new Model
|
|
||||||
m_Model=new CModel;
|
|
||||||
m_Model->InitModel(modeldef);
|
|
||||||
|
|
||||||
CStr texturefilename(m_TextureName);
|
|
||||||
|
|
||||||
m_Model->SetTexture(CTexture((const char*) texturefilename));
|
|
||||||
|
|
||||||
for( uint t = 0; t < m_Animations.size(); t++ )
|
|
||||||
{
|
|
||||||
if( m_Animations[t].m_FileName.Length() > 0 )
|
|
||||||
{
|
|
||||||
CStr animfilename( "mods\\official\\" );
|
|
||||||
animfilename += m_Animations[t].m_FileName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_Animations[t].m_AnimData = CSkeletonAnim::Load( animfilename );
|
|
||||||
}
|
|
||||||
catch( ... )
|
|
||||||
{
|
|
||||||
m_Animations[t].m_AnimData = NULL;
|
|
||||||
}
|
|
||||||
if( m_Animations[t].m_AnimName.LowerCase() == CStr( "idle" ) )
|
|
||||||
m_IdleAnim = m_Animations[t].m_AnimData;
|
|
||||||
if( m_Animations[t].m_AnimName.LowerCase() == CStr( "walk" ) )
|
|
||||||
m_WalkAnim = m_Animations[t].m_AnimData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_Model->SetAnimation( m_IdleAnim );
|
|
||||||
|
|
||||||
// rebuild model bounds
|
|
||||||
m_Model->CalcBounds();
|
|
||||||
|
|
||||||
// replace any units using old model to now use new model
|
|
||||||
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
|
|
||||||
for (uint i=0;i<units.size();++i) {
|
|
||||||
if (units[i]->m_Model->GetModelDef()==oldmodel) {
|
|
||||||
units[i]->m_Model->InitModel(m_Model->GetModelDef());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// and were done with the old model ..
|
|
||||||
delete oldmodel;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSkeletonAnim* CObjectEntry::GetNamedAnimation( CStr animationName )
|
|
||||||
{
|
|
||||||
for( uint t = 0; t < m_Animations.size(); t++ )
|
|
||||||
{
|
|
||||||
if( m_Animations[t].m_AnimName == animationName )
|
|
||||||
return( m_Animations[t].m_AnimData );
|
|
||||||
}
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CObjectEntry::Load(const char* filename)
|
|
||||||
{
|
|
||||||
bool parseOK = false;
|
|
||||||
|
|
||||||
// Initialize XML library
|
|
||||||
XMLPlatformUtils::Initialize();
|
|
||||||
{
|
|
||||||
// Create parser instance
|
|
||||||
XercesDOMParser *parser = new XercesDOMParser();
|
|
||||||
|
|
||||||
// Setup parser
|
|
||||||
parser->setValidationScheme(XercesDOMParser::Val_Auto);
|
|
||||||
parser->setDoNamespaces(false);
|
|
||||||
parser->setDoSchema(false);
|
|
||||||
parser->setCreateEntityReferenceNodes(false);
|
|
||||||
|
|
||||||
// Set customized error handler
|
|
||||||
CXercesErrorHandler *errorHandler = new CXercesErrorHandler();
|
|
||||||
parser->setErrorHandler(errorHandler);
|
|
||||||
|
|
||||||
// Push the CLogger to mark it's reading this file.
|
|
||||||
|
|
||||||
// Get main node
|
|
||||||
LocalFileInputSource source( XMLString::transcode(filename) );
|
|
||||||
|
|
||||||
// Parse file
|
|
||||||
parser->parse(source);
|
|
||||||
|
|
||||||
// Check how many errors
|
|
||||||
parseOK = parser->getErrorCount() == 0;
|
|
||||||
|
|
||||||
if (parseOK) {
|
|
||||||
// parsed successfully - grab our data
|
|
||||||
DOMDocument *doc = parser->getDocument();
|
|
||||||
DOMElement *element = doc->getDocumentElement();
|
|
||||||
|
|
||||||
// root_name should be Object
|
|
||||||
CStr root_name = XMLString::transcode( element->getNodeName() );
|
|
||||||
|
|
||||||
// should have at least 3 children - Name, ModelName and TextureName
|
|
||||||
DOMNodeList *children = element->getChildNodes();
|
|
||||||
int numChildren=children->getLength();
|
|
||||||
for (int i=0; i<numChildren; ++i) {
|
|
||||||
// Get node
|
|
||||||
DOMNode *child = children->item(i);
|
|
||||||
|
|
||||||
// A child element
|
|
||||||
if (child->getNodeType() == DOMNode::ELEMENT_NODE)
|
|
||||||
{
|
|
||||||
// First get element and not node
|
|
||||||
DOMElement *child_element = (DOMElement*)child;
|
|
||||||
|
|
||||||
CStr element_name = XMLString::transcode( child_element->getNodeName() );
|
|
||||||
DOMNode *value_node= child_element->getChildNodes()->item(0);
|
|
||||||
CStr element_value=value_node ? XMLString::transcode(value_node->getNodeValue()) : "";
|
|
||||||
|
|
||||||
if (element_name==CStr("Name")) {
|
|
||||||
m_Name=element_value;
|
|
||||||
} else if (element_name==CStr("ModelName")) {
|
|
||||||
m_ModelName=element_value;
|
|
||||||
} else if (element_name==CStr("TextureName")) {
|
|
||||||
m_TextureName=element_value;
|
|
||||||
} else if (element_name==CStr("Animations")) {
|
|
||||||
DOMNodeList* animations=(DOMNodeList*) child_element->getChildNodes();
|
|
||||||
|
|
||||||
for (uint j=0; j<animations->getLength(); ++j) {
|
|
||||||
DOMElement *anim_element = (DOMElement*) animations->item(j);
|
|
||||||
CStr element_name = XMLString::transcode( anim_element->getNodeName() );
|
|
||||||
DOMNamedNodeMap* attributes=anim_element->getAttributes();
|
|
||||||
if (attributes) {
|
|
||||||
Anim anim;
|
|
||||||
|
|
||||||
DOMNode *nameattr=attributes->getNamedItem(XMLString::transcode("name"));
|
|
||||||
anim.m_AnimName=XMLString::transcode(nameattr->getChildNodes()->item(0)->getNodeValue());
|
|
||||||
DOMNode *fileattr=attributes->getNamedItem(XMLString::transcode("file"));
|
|
||||||
anim.m_FileName=XMLString::transcode(fileattr->getChildNodes()->item(0)->getNodeValue());
|
|
||||||
|
|
||||||
m_Animations.push_back(anim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try and build the model
|
|
||||||
BuildModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete parser;
|
|
||||||
}
|
|
||||||
XMLPlatformUtils::Terminate();
|
|
||||||
|
|
||||||
return parseOK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CObjectEntry::Save(const char* filename)
|
|
||||||
{
|
|
||||||
FILE* fp=fopen(filename,"w");
|
|
||||||
if (!fp) return false;
|
|
||||||
|
|
||||||
// write XML header
|
|
||||||
fprintf(fp,"<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>\n\n");
|
|
||||||
fprintf(fp,"<!DOCTYPE Object SYSTEM \"..\\object.dtd\">\n\n");
|
|
||||||
|
|
||||||
// write the object itself
|
|
||||||
fprintf(fp,"<!-- File automatically generated by ScEd -->\n");
|
|
||||||
fprintf(fp,"<Object>\n");
|
|
||||||
fprintf(fp,"\t<Name>%s</Name>\n",(const char*) m_Name);
|
|
||||||
fprintf(fp,"\t<ModelName>%s</ModelName>\n",(const char*) m_ModelName);
|
|
||||||
fprintf(fp,"\t<TextureName>%s</TextureName>\n",(const char*) m_TextureName);
|
|
||||||
if (m_Animations.size()>0) {
|
|
||||||
fprintf(fp,"\t<Animations>\n");
|
|
||||||
for (uint i=0;i<m_Animations.size();i++) {
|
|
||||||
fprintf(fp,"\t\t<Animation name=\"%s\" file=\"%s\"> </Animation>\n",(const char*) m_Animations[i].m_AnimName,(const char*) m_Animations[i].m_FileName);
|
|
||||||
}
|
|
||||||
fprintf(fp,"\t</Animations>\n");
|
|
||||||
}
|
|
||||||
fprintf(fp,"</Object>\n");
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef _OBJECTENTRY_H
|
|
||||||
#define _OBJECTENTRY_H
|
|
||||||
|
|
||||||
class CModel;
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "CStr.h"
|
|
||||||
#include "terrain/Bound.h"
|
|
||||||
#include "terrain/ModelDef.h"
|
|
||||||
|
|
||||||
class CObjectEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Anim {
|
|
||||||
CStr m_AnimName;
|
|
||||||
CStr m_FileName;
|
|
||||||
CSkeletonAnim* m_AnimData;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
CObjectEntry(int type);
|
|
||||||
~CObjectEntry();
|
|
||||||
|
|
||||||
bool BuildModel();
|
|
||||||
|
|
||||||
bool Load(const char* filename);
|
|
||||||
bool Save(const char* filename);
|
|
||||||
|
|
||||||
// object name
|
|
||||||
CStr m_Name;
|
|
||||||
// texture name
|
|
||||||
CStr m_TextureName;
|
|
||||||
// model name
|
|
||||||
CStr m_ModelName;
|
|
||||||
// animations
|
|
||||||
std::vector<Anim> m_Animations;
|
|
||||||
CSkeletonAnim* m_IdleAnim;
|
|
||||||
CSkeletonAnim* m_WalkAnim;
|
|
||||||
CSkeletonAnim* m_DeathAnim;
|
|
||||||
CSkeletonAnim* m_MeleeAnim;
|
|
||||||
CSkeletonAnim* m_RangedAnim;
|
|
||||||
CSkeletonAnim* GetNamedAnimation( CStr animationName );
|
|
||||||
// object space bounds of model
|
|
||||||
// CBound m_Bound;
|
|
||||||
// corresponding model
|
|
||||||
CModel* m_Model;
|
|
||||||
// type of object; index into object managers types array
|
|
||||||
int m_Type;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
|||||||
#include "ObjectManager.h"
|
|
||||||
#include <io.h>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
CObjectManager g_ObjMan;
|
|
||||||
|
|
||||||
CObjectManager::CObjectManager() : m_SelectedObject(0)
|
|
||||||
{
|
|
||||||
m_ObjectTypes.reserve(32);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CObjectEntry* CObjectManager::FindObject(const char* objectname)
|
|
||||||
{
|
|
||||||
for (uint k=0;k<m_ObjectTypes.size();k++) {
|
|
||||||
std::vector<CObjectEntry*>& objects=m_ObjectTypes[k].m_Objects;
|
|
||||||
|
|
||||||
for (uint i=0;i<objects.size();i++) {
|
|
||||||
if (strcmp(objectname,(const char*) objects[i]->m_Name)==0) {
|
|
||||||
return objects[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::AddObjectType(const char* name)
|
|
||||||
{
|
|
||||||
m_ObjectTypes.resize(m_ObjectTypes.size()+1);
|
|
||||||
SObjectType& type=m_ObjectTypes.back();
|
|
||||||
type.m_Name=name;
|
|
||||||
type.m_Index=(int)m_ObjectTypes.size()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::AddObject(CObjectEntry* object,int type)
|
|
||||||
{
|
|
||||||
assert((uint)type<m_ObjectTypes.size());
|
|
||||||
if( object->BuildModel() )
|
|
||||||
m_ObjectTypes[type].m_Objects.push_back(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::DeleteObject(CObjectEntry* entry)
|
|
||||||
{
|
|
||||||
std::vector<CObjectEntry*>& objects=m_ObjectTypes[entry->m_Type].m_Objects;
|
|
||||||
|
|
||||||
typedef std::vector<CObjectEntry*>::iterator Iter;
|
|
||||||
Iter i=std::find(objects.begin(),objects.end(),entry);
|
|
||||||
if (i!=objects.end()) {
|
|
||||||
objects.erase(i);
|
|
||||||
}
|
|
||||||
delete entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::LoadObjects()
|
|
||||||
{
|
|
||||||
// find all the object types by directory name
|
|
||||||
BuildObjectTypes();
|
|
||||||
|
|
||||||
// now iterate through terrain types loading all textures of that type
|
|
||||||
for (uint i=0;i<m_ObjectTypes.size();i++) {
|
|
||||||
LoadObjects(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::BuildObjectTypes()
|
|
||||||
{
|
|
||||||
struct _finddata_t file;
|
|
||||||
intptr_t handle;
|
|
||||||
|
|
||||||
// Find first matching directory in terrain\textures
|
|
||||||
if ((handle=_findfirst("mods\\official\\art\\actors\\*",&file))!=-1) {
|
|
||||||
|
|
||||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
|
||||||
AddObjectType(file.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the rest of the matching files
|
|
||||||
while( _findnext(handle,&file)==0) {
|
|
||||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
|
||||||
AddObjectType(file.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_findclose(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CObjectManager::LoadObjects(int type)
|
|
||||||
{
|
|
||||||
struct _finddata_t file;
|
|
||||||
intptr_t handle;
|
|
||||||
|
|
||||||
// build pathname
|
|
||||||
CStr pathname("mods\\official\\art\\actors\\");
|
|
||||||
pathname+=m_ObjectTypes[type].m_Name;
|
|
||||||
pathname+="\\";
|
|
||||||
|
|
||||||
CStr findname(pathname);
|
|
||||||
findname+="*.xml";
|
|
||||||
|
|
||||||
// Find first matching file in directory for this terrain type
|
|
||||||
if ((handle=_findfirst((const char*) findname,&file))!=-1) {
|
|
||||||
|
|
||||||
CObjectEntry* object=new CObjectEntry(type);
|
|
||||||
CStr filename(pathname);
|
|
||||||
filename+=file.name;
|
|
||||||
if (!object->Load((const char*) filename)) {
|
|
||||||
delete object;
|
|
||||||
} else {
|
|
||||||
AddObject(object,type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the rest of the matching files
|
|
||||||
while( _findnext(handle,&file)==0) {
|
|
||||||
CObjectEntry* object=new CObjectEntry(type);
|
|
||||||
CStr filename(pathname);
|
|
||||||
filename+=file.name;
|
|
||||||
if (!object->Load((const char*) filename)) {
|
|
||||||
delete object;
|
|
||||||
} else {
|
|
||||||
AddObject(object,type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_findclose(handle);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
#ifndef _OBJECTMANAGER_H
|
|
||||||
#define _OBJECTMANAGER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "ObjectEntry.h"
|
|
||||||
|
|
||||||
class CObjectManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct SObjectType
|
|
||||||
{
|
|
||||||
// name of this object type (derived from directory name)
|
|
||||||
CStr m_Name;
|
|
||||||
// index in parent array
|
|
||||||
int m_Index;
|
|
||||||
// list of objects of this type (found from the objects directory)
|
|
||||||
std::vector<CObjectEntry*> m_Objects;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
CObjectManager();
|
|
||||||
|
|
||||||
void LoadObjects();
|
|
||||||
|
|
||||||
|
|
||||||
void AddObjectType(const char* name);
|
|
||||||
|
|
||||||
CObjectEntry* FindObject(const char* objname);
|
|
||||||
void AddObject(CObjectEntry* entry,int type);
|
|
||||||
void DeleteObject(CObjectEntry* entry);
|
|
||||||
|
|
||||||
CObjectEntry* GetSelectedObject() const { return m_SelectedObject; }
|
|
||||||
void SetSelectedObject(CObjectEntry* obj) { m_SelectedObject=obj; }
|
|
||||||
|
|
||||||
std::vector<SObjectType> m_ObjectTypes;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void BuildObjectTypes();
|
|
||||||
void LoadObjects(int type);
|
|
||||||
|
|
||||||
CObjectEntry* m_SelectedObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CObjectManager g_ObjMan;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,86 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: Particle.cpp
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: A single particle, currently only utilized by
|
|
||||||
| CParticleEmitter. Public variables are for performance
|
|
||||||
| reasons.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: Instantiate a particle, set public variables, then call
|
|
||||||
| Frame() every frame.
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#include "Particle.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "ogl.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
CParticle::CParticle() :
|
|
||||||
m_duration(0.0f),
|
|
||||||
m_timeElapsedTotal(0.0f),
|
|
||||||
m_position(0.0f, 0.0f, 0.0f),
|
|
||||||
m_velocity(0.0f, 0.0f, 0.0f),
|
|
||||||
m_gravity(0.0f, 0.0f, 0.0f)
|
|
||||||
{
|
|
||||||
m_timeOfLastFrame = get_time();
|
|
||||||
|
|
||||||
// default white colour
|
|
||||||
m_colour[0] = m_colour[1] = m_colour[2] = m_colour[3] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
CParticle::~CParticle()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticle::Init()
|
|
||||||
{
|
|
||||||
// calculate colour increment per second in order to fade to black
|
|
||||||
m_colourInc[0] = - (m_colour[0] / m_duration);
|
|
||||||
m_colourInc[1] = - (m_colour[1] / m_duration);
|
|
||||||
m_colourInc[2] = - (m_colour[2] / m_duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticle::Frame()
|
|
||||||
{
|
|
||||||
Update();
|
|
||||||
Render();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticle::Render()
|
|
||||||
{
|
|
||||||
assert(m_sprite);
|
|
||||||
|
|
||||||
m_sprite->SetColour(m_colour);
|
|
||||||
m_sprite->SetTranslation(m_position);
|
|
||||||
m_sprite->Render();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticle::Update()
|
|
||||||
{
|
|
||||||
float timeElapsed = float(get_time() - m_timeOfLastFrame);
|
|
||||||
|
|
||||||
m_velocity += m_gravity * timeElapsed;
|
|
||||||
m_position += m_velocity * timeElapsed;
|
|
||||||
|
|
||||||
// fade colour
|
|
||||||
m_colour[0] += m_colourInc[0] * timeElapsed;
|
|
||||||
m_colour[1] += m_colourInc[1] * timeElapsed;
|
|
||||||
m_colour[2] += m_colourInc[2] * timeElapsed;
|
|
||||||
|
|
||||||
m_timeOfLastFrame = get_time();
|
|
||||||
m_timeElapsedTotal += timeElapsed;
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: Particle.h
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: A single particle, currently only utilized by
|
|
||||||
| CParticleEmitter. Public variables are for performance
|
|
||||||
| reasons.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: Instantiate a particle, set public variables, then call
|
|
||||||
| Frame() every frame.
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#ifndef PARTICLE_H
|
|
||||||
#define PARTICLE_H
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Includes / Compiler directives
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Sprite.h"
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Declarations
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
class CParticle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CParticle();
|
|
||||||
~CParticle();
|
|
||||||
|
|
||||||
// necessary pre-processing immediately before first update call
|
|
||||||
void Init();
|
|
||||||
|
|
||||||
void Frame();
|
|
||||||
void Update();
|
|
||||||
void Render();
|
|
||||||
|
|
||||||
void SetColour(float r, float g, float b, float a);
|
|
||||||
|
|
||||||
CSprite * m_sprite;
|
|
||||||
|
|
||||||
float m_duration;
|
|
||||||
double m_timeOfLastFrame;
|
|
||||||
double m_timeElapsedTotal;
|
|
||||||
|
|
||||||
CVector3D m_position;
|
|
||||||
CVector3D m_velocity;
|
|
||||||
CVector3D m_gravity;
|
|
||||||
|
|
||||||
float m_colour[4];
|
|
||||||
float m_colourInc[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PARTICLE_H
|
|
@ -1,277 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: ParticleEmitter.cpp
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: Particle emitter class that emits particles from
|
|
||||||
| an origin (or area) with a variety of set colours,
|
|
||||||
| durations, forces and a single common sprite.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: Instantiate one emitter per desired effect. Set the
|
|
||||||
| various fields (preferably all, the defaults are rather
|
|
||||||
| boring) and then call Frame() - you guessed it - every
|
|
||||||
| frame.
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#include "ParticleEmitter.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "ogl.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
CParticleEmitter::CParticleEmitter() :
|
|
||||||
m_particles(NULL),
|
|
||||||
m_origin(0.0f, 0.0f, 0.0f),
|
|
||||||
m_originSpread(0.0f, 0.0f, 0.0f),
|
|
||||||
m_velocity(0.0f, 0.0f, 0.0f),
|
|
||||||
m_velocitySpread(0.0f, 0.0f, 0.0f),
|
|
||||||
m_gravity(0.0f, 0.0f, 0.0f),
|
|
||||||
m_maxParticles(0),
|
|
||||||
m_minParticles(0),
|
|
||||||
m_numParticles(0),
|
|
||||||
m_maxLifetime(0),
|
|
||||||
m_minLifetime(0),
|
|
||||||
m_timeOfLastFrame(0.0f),
|
|
||||||
m_timeSinceLastEmit(0.0f)
|
|
||||||
{
|
|
||||||
m_particles.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
CParticleEmitter::~CParticleEmitter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::Frame()
|
|
||||||
{
|
|
||||||
Update();
|
|
||||||
Render();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::Render()
|
|
||||||
{
|
|
||||||
|
|
||||||
glEnable(GL_ALPHA_TEST);
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
glAlphaFunc(GL_GREATER, 0.0f);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
|
||||||
|
|
||||||
vector<CParticle *>::iterator itor = m_particles.begin();
|
|
||||||
while (itor != m_particles.end())
|
|
||||||
{
|
|
||||||
CParticle * curParticle = (*itor);
|
|
||||||
|
|
||||||
curParticle->Frame();
|
|
||||||
++itor;
|
|
||||||
}
|
|
||||||
glDisable(GL_ALPHA_TEST);
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::Update()
|
|
||||||
{
|
|
||||||
double timeElapsed = get_time() - m_timeOfLastFrame;
|
|
||||||
|
|
||||||
// update existing particles
|
|
||||||
vector<CParticle *>::iterator itor = m_particles.begin();
|
|
||||||
while (itor != m_particles.end())
|
|
||||||
{
|
|
||||||
CParticle * curParticle = (*itor);
|
|
||||||
|
|
||||||
curParticle->Update();
|
|
||||||
|
|
||||||
// destroy particle if it has lived beyond its duration
|
|
||||||
if (curParticle->m_timeElapsedTotal >= curParticle->m_duration)
|
|
||||||
{
|
|
||||||
m_particles.erase(itor);
|
|
||||||
delete curParticle;
|
|
||||||
--m_numParticles;
|
|
||||||
}
|
|
||||||
|
|
||||||
++itor;
|
|
||||||
}
|
|
||||||
|
|
||||||
double secondsPerEmit = 1 / (m_minParticles / m_minLifetime);
|
|
||||||
|
|
||||||
if (m_timeSinceLastEmit > secondsPerEmit)
|
|
||||||
{
|
|
||||||
|
|
||||||
float duration;
|
|
||||||
CVector3D position, velocity;
|
|
||||||
float colour[4];
|
|
||||||
|
|
||||||
bool moreParticlesToEmit = true;
|
|
||||||
while (moreParticlesToEmit) {
|
|
||||||
CParticle * newParticle = new CParticle();
|
|
||||||
|
|
||||||
// calculate particle duration
|
|
||||||
duration = (float)m_minLifetime;
|
|
||||||
duration += (rand() % (int)((m_maxLifetime - m_minLifetime) * 1000.0f + 1)) / 1000.0f;
|
|
||||||
newParticle->m_duration = duration;
|
|
||||||
|
|
||||||
// calculate particle start position from spread
|
|
||||||
position = m_origin;
|
|
||||||
position.X += (rand() % (int)(m_originSpread.X * 2000.0f + 1)) / 1000.0f - m_originSpread.X;
|
|
||||||
position.Y += (rand() % (int)(m_originSpread.Y * 2000.0f + 1)) / 1000.0f - m_originSpread.Y;
|
|
||||||
position.Z += (rand() % (int)(m_originSpread.Z * 2000.0f + 1)) / 1000.0f - m_originSpread.Z;
|
|
||||||
newParticle->m_position = position;
|
|
||||||
|
|
||||||
// calculate particle velocity from spread
|
|
||||||
velocity = m_velocity;
|
|
||||||
velocity.X += (rand() % (int)(m_velocitySpread.X * 2000.0f + 1)) / 1000.0f - m_velocitySpread.X;
|
|
||||||
velocity.Y += (rand() % (int)(m_velocitySpread.Y * 2000.0f + 1)) / 1000.0f - m_velocitySpread.Y;
|
|
||||||
velocity.Z += (rand() % (int)(m_velocitySpread.Z * 2000.0f + 1)) / 1000.0f - m_velocitySpread.Z;
|
|
||||||
newParticle->m_velocity = velocity;
|
|
||||||
|
|
||||||
newParticle->m_gravity = m_gravity;
|
|
||||||
|
|
||||||
// calculate and assign colour
|
|
||||||
memcpy(colour, m_startColour, sizeof(float) * 4);
|
|
||||||
colour[0] += (rand() % (int)((m_endColour[0] - m_startColour[0]) * 1000.0f + 1)) / 1000.0f;
|
|
||||||
colour[1] += (rand() % (int)((m_endColour[1] - m_startColour[1]) * 1000.0f + 1)) / 1000.0f;
|
|
||||||
colour[2] += (rand() % (int)((m_endColour[2] - m_startColour[2]) * 1000.0f + 1)) / 1000.0f;
|
|
||||||
colour[3] += (rand() % (int)((m_endColour[3] - m_startColour[3]) * 1000.0f + 1)) / 1000.0f;
|
|
||||||
memcpy(newParticle->m_colour, colour, sizeof(float) * 4);
|
|
||||||
|
|
||||||
// assign sprite
|
|
||||||
newParticle->m_sprite = m_sprite;
|
|
||||||
|
|
||||||
// final pre-processing init call
|
|
||||||
newParticle->Init();
|
|
||||||
|
|
||||||
// add to vector of particles
|
|
||||||
m_particles.push_back(newParticle);
|
|
||||||
|
|
||||||
timeElapsed -= secondsPerEmit;
|
|
||||||
if (timeElapsed < secondsPerEmit)
|
|
||||||
{
|
|
||||||
moreParticlesToEmit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
++m_numParticles;
|
|
||||||
}
|
|
||||||
m_timeSinceLastEmit = 0.0f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_timeSinceLastEmit += (float)timeElapsed;
|
|
||||||
|
|
||||||
m_timeOfLastFrame = get_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetSprite(CSprite * sprite)
|
|
||||||
{
|
|
||||||
m_sprite = sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetOrigin(CVector3D origin)
|
|
||||||
{
|
|
||||||
m_origin = origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetOrigin(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_origin.X = x;
|
|
||||||
m_origin.Y = y;
|
|
||||||
m_origin.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetOriginSpread(CVector3D spread)
|
|
||||||
{
|
|
||||||
m_originSpread = spread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetOriginSpread(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_originSpread.X = x;
|
|
||||||
m_originSpread.Y = y;
|
|
||||||
m_originSpread.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetGravity(CVector3D gravity)
|
|
||||||
{
|
|
||||||
m_gravity = gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetGravity(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_gravity.X = x;
|
|
||||||
m_gravity.Y = y;
|
|
||||||
m_gravity.Z = z;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetVelocity(CVector3D velocity)
|
|
||||||
{
|
|
||||||
m_velocity = velocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetVelocity(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_velocity.X = x;
|
|
||||||
m_velocity.Y = y;
|
|
||||||
m_velocity.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CParticleEmitter::SetVelocitySpread(CVector3D spread)
|
|
||||||
{
|
|
||||||
m_velocitySpread = spread;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetVelocitySpread(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_velocitySpread.X = x;
|
|
||||||
m_velocitySpread.Y = y;
|
|
||||||
m_velocitySpread.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetStartColour(float r, float g, float b, float a)
|
|
||||||
{
|
|
||||||
m_startColour[0] = r;
|
|
||||||
m_startColour[1] = g;
|
|
||||||
m_startColour[2] = b;
|
|
||||||
m_startColour[3] = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetEndColour(float r, float g, float b, float a)
|
|
||||||
{
|
|
||||||
m_endColour[0] = r;
|
|
||||||
m_endColour[1] = g;
|
|
||||||
m_endColour[2] = b;
|
|
||||||
m_endColour[3] = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetMaxLifetime(double maxLife)
|
|
||||||
{
|
|
||||||
m_maxLifetime = maxLife;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetMinLifetime(double minLife)
|
|
||||||
{
|
|
||||||
m_minLifetime = minLife;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetMaxParticles(int maxParticles)
|
|
||||||
{
|
|
||||||
m_maxParticles = maxParticles;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CParticleEmitter::SetMinParticles(int minParticles)
|
|
||||||
{
|
|
||||||
m_minParticles = minParticles;
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: ParticleEmitter.h
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: Particle emitter class that emits particles from
|
|
||||||
| an origin (or area) with a variety of set colours,
|
|
||||||
| durations, forces and a single common sprite.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: Instantiate one emitter per desired effect. Set the
|
|
||||||
| various fields (preferably all, the defaults are rather
|
|
||||||
| boring) and then call Frame() - you guessed it - every
|
|
||||||
| frame.
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#ifndef PARTICLE_EMITTER_H
|
|
||||||
#define PARTICLE_EMITTER_H
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Includes / Compiler directives
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
#include "Particle.h"
|
|
||||||
#include "Sprite.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Declarations
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
class CParticleEmitter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CParticleEmitter();
|
|
||||||
~CParticleEmitter();
|
|
||||||
|
|
||||||
// must be performed before first frame/render/update call
|
|
||||||
bool Init();
|
|
||||||
|
|
||||||
// renders and updates particles
|
|
||||||
void Frame();
|
|
||||||
|
|
||||||
// renders without updating particles
|
|
||||||
void Render();
|
|
||||||
|
|
||||||
void Update();
|
|
||||||
|
|
||||||
void SetSprite(CSprite * sprite);
|
|
||||||
|
|
||||||
void SetOrigin(CVector3D origin);
|
|
||||||
void SetOrigin(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetOriginSpread(CVector3D spread);
|
|
||||||
void SetOriginSpread(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetGravity(CVector3D gravity);
|
|
||||||
void SetGravity(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetVelocity(CVector3D direction);
|
|
||||||
void SetVelocity(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetVelocitySpread(CVector3D spread);
|
|
||||||
void SetVelocitySpread(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetStartColour(float r, float g, float b, float a);
|
|
||||||
void SetEndColour(float r, float g, float b, float a);
|
|
||||||
|
|
||||||
// in milliseconds
|
|
||||||
void SetMaxLifetime(double maxLife);
|
|
||||||
|
|
||||||
// in milliseconds
|
|
||||||
void SetMinLifetime(double minLife);
|
|
||||||
|
|
||||||
void SetMaxParticles(int maxParticles);
|
|
||||||
void SetMinParticles(int minParticles);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CSprite * m_sprite;
|
|
||||||
|
|
||||||
std::vector<CParticle *> m_particles;
|
|
||||||
|
|
||||||
CVector3D m_origin;
|
|
||||||
CVector3D m_originSpread;
|
|
||||||
|
|
||||||
CVector3D m_velocity;
|
|
||||||
CVector3D m_velocitySpread;
|
|
||||||
|
|
||||||
CVector3D m_gravity;
|
|
||||||
|
|
||||||
float m_startColour[4];
|
|
||||||
float m_endColour[4];
|
|
||||||
|
|
||||||
int m_maxParticles;
|
|
||||||
int m_minParticles;
|
|
||||||
int m_numParticles;
|
|
||||||
|
|
||||||
double m_maxLifetime;
|
|
||||||
double m_minLifetime;
|
|
||||||
|
|
||||||
double m_timeOfLastFrame;
|
|
||||||
float m_timeSinceLastEmit;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PARTICLE_EMITTER_H
|
|
@ -1,60 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: ModelDef.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "Patch.h"
|
|
||||||
#include "Terrain.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CPatch constructor
|
|
||||||
CPatch::CPatch() : m_Parent(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CPatch destructor
|
|
||||||
CPatch::~CPatch()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Initialize: setup patch data
|
|
||||||
void CPatch::Initialize(CTerrain* parent,u32 x,u32 z)
|
|
||||||
{
|
|
||||||
delete m_RenderData;
|
|
||||||
m_RenderData=0;
|
|
||||||
|
|
||||||
m_Parent=parent;
|
|
||||||
m_X=x;
|
|
||||||
m_Z=z;
|
|
||||||
|
|
||||||
// set parent of each patch
|
|
||||||
for (int j=0;j<16;j++) {
|
|
||||||
for (int i=0;i<16;i++) {
|
|
||||||
m_MiniPatches[j][i].m_Parent=this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CalcBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CalcBounds: calculating the bounds of this patch
|
|
||||||
void CPatch::CalcBounds()
|
|
||||||
{
|
|
||||||
m_Bounds.SetEmpty();
|
|
||||||
|
|
||||||
for (int j=0;j<PATCH_SIZE+1;j++) {
|
|
||||||
for (int i=0;i<PATCH_SIZE+1;i++) {
|
|
||||||
CVector3D pos;
|
|
||||||
m_Parent->CalcPosition(m_X*PATCH_SIZE+i,m_Z*PATCH_SIZE+j,pos);
|
|
||||||
m_Bounds+=pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Patch.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _PATCH_H
|
|
||||||
#define _PATCH_H
|
|
||||||
|
|
||||||
#include "MiniPatch.h"
|
|
||||||
#include "RenderableObject.h"
|
|
||||||
|
|
||||||
class CTerrain;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CPatch: a single terrain patch, 16 tiles square
|
|
||||||
class CPatch : public CRenderableObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CPatch();
|
|
||||||
// destructor
|
|
||||||
~CPatch();
|
|
||||||
|
|
||||||
// initialize the patch
|
|
||||||
void Initialize(CTerrain* parent,u32 x,u32 z);
|
|
||||||
// calculate and store bounds of this patch
|
|
||||||
void CalcBounds();
|
|
||||||
|
|
||||||
public:
|
|
||||||
// minipatches (tiles) making up the patch
|
|
||||||
CMiniPatch m_MiniPatches[16][16];
|
|
||||||
// position of patch in parent terrain grid
|
|
||||||
u32 m_X,m_Z;
|
|
||||||
// parent terrain
|
|
||||||
CTerrain* m_Parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,554 +0,0 @@
|
|||||||
#pragma warning(disable:4786)
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "res/tex.h"
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "PatchRData.h"
|
|
||||||
#include "AlphaMapCalculator.h"
|
|
||||||
|
|
||||||
const int BlendOffsets[8][2] = {
|
|
||||||
{ 0, -1 },
|
|
||||||
{ -1, -1 },
|
|
||||||
{ -1, 0 },
|
|
||||||
{ -1, 1 },
|
|
||||||
{ 0, 1 },
|
|
||||||
{ 1, 1 },
|
|
||||||
{ 1, 0 },
|
|
||||||
{ 1, -1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_Vertices(0), m_VBBase(0), m_VBBlends(0)
|
|
||||||
{
|
|
||||||
assert(patch);
|
|
||||||
Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
CPatchRData::~CPatchRData()
|
|
||||||
{
|
|
||||||
delete[] m_Vertices;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Handle GetTerrainTileTexture(CTerrain* terrain,int gx,int gz)
|
|
||||||
{
|
|
||||||
CMiniPatch* mp=terrain->GetTile(gx,gz);
|
|
||||||
return mp ? mp->Tex1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QueryAdjacency(int x,int y,Handle h,Handle* texgrid)
|
|
||||||
{
|
|
||||||
for (int j=y-1;j<=y+1;j++) {
|
|
||||||
for (int i=x-1;i<=x+1;i++) {
|
|
||||||
if (i<0 || i>PATCH_SIZE+1 || j<0 || j>PATCH_SIZE+1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texgrid[j*(PATCH_SIZE+2)+i]==h) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct STmpSplat {
|
|
||||||
Handle m_Texture;
|
|
||||||
u16 m_Indices[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
void CPatchRData::BuildBlends()
|
|
||||||
{
|
|
||||||
m_BlendIndices.clear();
|
|
||||||
m_BlendSplats.clear();
|
|
||||||
m_BlendVertices.clear();
|
|
||||||
|
|
||||||
// get index of this patch
|
|
||||||
int px=m_Patch->m_X;
|
|
||||||
int pz=m_Patch->m_Z;
|
|
||||||
|
|
||||||
CTerrain* terrain=m_Patch->m_Parent;
|
|
||||||
|
|
||||||
// temporary list of splats
|
|
||||||
std::vector<STmpSplat> splats;
|
|
||||||
// set of textures used for splats
|
|
||||||
std::set<Handle> splatTextures;
|
|
||||||
|
|
||||||
// for each tile in patch ..
|
|
||||||
for (int j=0;j<PATCH_SIZE;j++) {
|
|
||||||
for (int i=0;i<PATCH_SIZE;i++) {
|
|
||||||
u32 gx,gz;
|
|
||||||
CMiniPatch* mp=&m_Patch->m_MiniPatches[j][i];
|
|
||||||
mp->GetTileIndex(gx,gz);
|
|
||||||
|
|
||||||
// build list of textures of higher priority than current tile that are used by neighbouring tiles
|
|
||||||
std::vector<STex> neighbourTextures;
|
|
||||||
for (int m=-1;m<=1;m++) {
|
|
||||||
for (int k=-1;k<=1;k++) {
|
|
||||||
CMiniPatch* nmp=terrain->GetTile(gx+k,gz+m);
|
|
||||||
if (nmp) {
|
|
||||||
if (nmp->Tex1Priority>mp->Tex1Priority || (nmp->Tex1Priority==mp->Tex1Priority && nmp->Tex1>mp->Tex1)) {
|
|
||||||
STex tex;
|
|
||||||
tex.m_Handle=nmp->Tex1;
|
|
||||||
tex.m_Priority=nmp->Tex1Priority;
|
|
||||||
if (std::find(neighbourTextures.begin(),neighbourTextures.end(),tex)==neighbourTextures.end()) {
|
|
||||||
neighbourTextures.push_back(tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (neighbourTextures.size()>0) {
|
|
||||||
// u32 count=neighbourTextures.size();
|
|
||||||
// janwas fixing warnings: not used?
|
|
||||||
// sort textures from lowest to highest priority
|
|
||||||
std::sort(neighbourTextures.begin(),neighbourTextures.end());
|
|
||||||
|
|
||||||
// for each of the neighbouring textures ..
|
|
||||||
for (uint k=0;k<neighbourTextures.size();++k) {
|
|
||||||
|
|
||||||
// now build the grid of blends dependent on whether the tile adjacent to the current tile
|
|
||||||
// uses the current neighbour texture
|
|
||||||
BlendShape8 shape;
|
|
||||||
for (int m=0;m<8;m++) {
|
|
||||||
int ox=gx+BlendOffsets[m][1];
|
|
||||||
int oz=gz+BlendOffsets[m][0];
|
|
||||||
|
|
||||||
// get texture on adjacent tile
|
|
||||||
Handle atex=GetTerrainTileTexture(terrain,ox,oz);
|
|
||||||
// fill 0/1 into shape array
|
|
||||||
shape[m]=(atex==neighbourTextures[k].m_Handle) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate the required alphamap and the required rotation of the alphamap from blendshape
|
|
||||||
unsigned int alphamapflags;
|
|
||||||
int alphamap=CAlphaMapCalculator::Calculate(shape,alphamapflags);
|
|
||||||
|
|
||||||
// now actually render the blend tile (if we need one)
|
|
||||||
if (alphamap!=-1) {
|
|
||||||
float u0=g_Renderer.m_AlphaMapCoords[alphamap].u0;
|
|
||||||
float u1=g_Renderer.m_AlphaMapCoords[alphamap].u1;
|
|
||||||
float v0=g_Renderer.m_AlphaMapCoords[alphamap].v0;
|
|
||||||
float v1=g_Renderer.m_AlphaMapCoords[alphamap].v1;
|
|
||||||
if (alphamapflags & BLENDMAP_FLIPU) {
|
|
||||||
// flip u
|
|
||||||
float t=u0;
|
|
||||||
u0=u1;
|
|
||||||
u1=t;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alphamapflags & BLENDMAP_FLIPV) {
|
|
||||||
// flip v
|
|
||||||
float t=v0;
|
|
||||||
v0=v1;
|
|
||||||
v1=t;
|
|
||||||
}
|
|
||||||
|
|
||||||
int base=0;
|
|
||||||
if (alphamapflags & BLENDMAP_ROTATE90) {
|
|
||||||
// rotate 1
|
|
||||||
base=1;
|
|
||||||
} else if (alphamapflags & BLENDMAP_ROTATE180) {
|
|
||||||
// rotate 2
|
|
||||||
base=2;
|
|
||||||
} else if (alphamapflags & BLENDMAP_ROTATE270) {
|
|
||||||
// rotate 3
|
|
||||||
base=3;
|
|
||||||
}
|
|
||||||
|
|
||||||
SBlendVertex vtx[4];
|
|
||||||
vtx[(base+0)%4].m_AlphaUVs[0]=u0;
|
|
||||||
vtx[(base+0)%4].m_AlphaUVs[1]=v0;
|
|
||||||
vtx[(base+1)%4].m_AlphaUVs[0]=u1;
|
|
||||||
vtx[(base+1)%4].m_AlphaUVs[1]=v0;
|
|
||||||
vtx[(base+2)%4].m_AlphaUVs[0]=u1;
|
|
||||||
vtx[(base+2)%4].m_AlphaUVs[1]=v1;
|
|
||||||
vtx[(base+3)%4].m_AlphaUVs[0]=u0;
|
|
||||||
vtx[(base+3)%4].m_AlphaUVs[1]=v1;
|
|
||||||
|
|
||||||
int vsize=PATCH_SIZE+1;
|
|
||||||
|
|
||||||
SBlendVertex dst;
|
|
||||||
int vindex=(int)m_BlendVertices.size();
|
|
||||||
|
|
||||||
const SBaseVertex& vtx0=m_Vertices[(j*vsize)+i];
|
|
||||||
dst.m_UVs[0]=i*0.125f;
|
|
||||||
dst.m_UVs[1]=j*0.125f;
|
|
||||||
dst.m_AlphaUVs[0]=vtx[0].m_AlphaUVs[0];
|
|
||||||
dst.m_AlphaUVs[1]=vtx[0].m_AlphaUVs[1];
|
|
||||||
dst.m_Color=vtx0.m_Color;
|
|
||||||
dst.m_Position=vtx0.m_Position;
|
|
||||||
m_BlendVertices.push_back(dst);
|
|
||||||
|
|
||||||
const SBaseVertex& vtx1=m_Vertices[(j*vsize)+i+1];
|
|
||||||
dst.m_UVs[0]=(i+1)*0.125f;
|
|
||||||
dst.m_UVs[1]=j*0.125f;
|
|
||||||
dst.m_AlphaUVs[0]=vtx[1].m_AlphaUVs[0];
|
|
||||||
dst.m_AlphaUVs[1]=vtx[1].m_AlphaUVs[1];
|
|
||||||
dst.m_Color=vtx1.m_Color;
|
|
||||||
dst.m_Position=vtx1.m_Position;
|
|
||||||
m_BlendVertices.push_back(dst);
|
|
||||||
|
|
||||||
const SBaseVertex& vtx2=m_Vertices[((j+1)*vsize)+i+1];
|
|
||||||
dst.m_UVs[0]=(i+1)*0.125f;
|
|
||||||
dst.m_UVs[1]=(j+1)*0.125f;
|
|
||||||
dst.m_AlphaUVs[0]=vtx[2].m_AlphaUVs[0];
|
|
||||||
dst.m_AlphaUVs[1]=vtx[2].m_AlphaUVs[1];
|
|
||||||
dst.m_Color=vtx2.m_Color;
|
|
||||||
dst.m_Position=vtx2.m_Position;
|
|
||||||
m_BlendVertices.push_back(dst);
|
|
||||||
|
|
||||||
const SBaseVertex& vtx3=m_Vertices[((j+1)*vsize)+i];
|
|
||||||
dst.m_UVs[0]=i*0.125f;
|
|
||||||
dst.m_UVs[1]=(j+1)*0.125f;
|
|
||||||
dst.m_AlphaUVs[0]=vtx[3].m_AlphaUVs[0];
|
|
||||||
dst.m_AlphaUVs[1]=vtx[3].m_AlphaUVs[1];
|
|
||||||
dst.m_Color=vtx3.m_Color;
|
|
||||||
dst.m_Position=vtx3.m_Position;
|
|
||||||
m_BlendVertices.push_back(dst);
|
|
||||||
|
|
||||||
// build a splat for this quad
|
|
||||||
STmpSplat splat;
|
|
||||||
splat.m_Texture=neighbourTextures[k].m_Handle;
|
|
||||||
splat.m_Indices[0]=vindex;
|
|
||||||
splat.m_Indices[1]=vindex+1;
|
|
||||||
splat.m_Indices[2]=vindex+2;
|
|
||||||
splat.m_Indices[3]=vindex+3;
|
|
||||||
splats.push_back(splat);
|
|
||||||
|
|
||||||
// add this texture to set of unique splat textures
|
|
||||||
splatTextures.insert(splat.m_Texture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now build outgoing splats
|
|
||||||
m_BlendSplats.resize(splatTextures.size());
|
|
||||||
int splatCount=0;
|
|
||||||
|
|
||||||
std::set<Handle>::iterator iter=splatTextures.begin();
|
|
||||||
for (;iter!=splatTextures.end();++iter) {
|
|
||||||
Handle tex=*iter;
|
|
||||||
|
|
||||||
SSplat& splat=m_BlendSplats[splatCount];
|
|
||||||
splat.m_IndexStart=(u32)m_BlendIndices.size();
|
|
||||||
splat.m_Texture=tex;
|
|
||||||
|
|
||||||
for (uint k=0;k<splats.size();k++) {
|
|
||||||
if (splats[k].m_Texture==tex) {
|
|
||||||
m_BlendIndices.push_back(splats[k].m_Indices[0]);
|
|
||||||
m_BlendIndices.push_back(splats[k].m_Indices[1]);
|
|
||||||
m_BlendIndices.push_back(splats[k].m_Indices[2]);
|
|
||||||
m_BlendIndices.push_back(splats[k].m_Indices[3]);
|
|
||||||
splat.m_IndexCount+=4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
splatCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
if (m_VBBlends) {
|
|
||||||
// destroy old buffer
|
|
||||||
glDeleteBuffersARB(1,(GLuint*) &m_VBBlends);
|
|
||||||
} else {
|
|
||||||
// generate buffer index
|
|
||||||
glGenBuffersARB(1,(GLuint*) &m_VBBlends);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new buffer
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBlends);
|
|
||||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,m_BlendVertices.size()*sizeof(SBlendVertex),&m_BlendVertices[0],GL_STATIC_DRAW_ARB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::BuildIndices()
|
|
||||||
{
|
|
||||||
// number of vertices in each direction in each patch
|
|
||||||
int vsize=PATCH_SIZE+1;
|
|
||||||
|
|
||||||
// release existing indices and bins
|
|
||||||
m_Indices.clear();
|
|
||||||
m_Splats.clear();
|
|
||||||
|
|
||||||
// build grid of textures on this patch and boundaries of adjacent patches
|
|
||||||
std::vector<Handle> textures;
|
|
||||||
Handle texgrid[PATCH_SIZE][PATCH_SIZE];
|
|
||||||
for (int j=0;j<PATCH_SIZE;j++) {
|
|
||||||
for (int i=0;i<PATCH_SIZE;i++) {
|
|
||||||
Handle h=m_Patch->m_MiniPatches[j][i].Tex1;
|
|
||||||
texgrid[j][i]=h;
|
|
||||||
if (std::find(textures.begin(),textures.end(),h)==textures.end()) {
|
|
||||||
textures.push_back(h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now build base splats from interior textures
|
|
||||||
m_Splats.resize(textures.size());
|
|
||||||
|
|
||||||
for (uint i=0;i<m_Splats.size();i++) {
|
|
||||||
Handle h=textures[i];
|
|
||||||
|
|
||||||
SSplat& splat=m_Splats[i];
|
|
||||||
splat.m_Texture=h;
|
|
||||||
splat.m_IndexStart=(u32)m_Indices.size();
|
|
||||||
|
|
||||||
for (int j=0;j<PATCH_SIZE;j++) {
|
|
||||||
for (int i=0;i<PATCH_SIZE;i++) {
|
|
||||||
if (texgrid[j][i]==h){
|
|
||||||
m_Indices.push_back(((j+0)*vsize+(i+0)));
|
|
||||||
m_Indices.push_back(((j+0)*vsize+(i+1)));
|
|
||||||
m_Indices.push_back(((j+1)*vsize+(i+1)));
|
|
||||||
m_Indices.push_back(((j+1)*vsize+(i+0)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
splat.m_IndexCount=(u32)(m_Indices.size()-splat.m_IndexStart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int clamp(int x,int min,int max)
|
|
||||||
{
|
|
||||||
if (x<min) return min;
|
|
||||||
else if (x>max) return max;
|
|
||||||
else return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SColor4ub ConvertColor(const RGBColor& src)
|
|
||||||
{
|
|
||||||
SColor4ub result;
|
|
||||||
result.R=clamp(int(src.X*255),0,255);
|
|
||||||
result.G=clamp(int(src.Y*255),0,255);
|
|
||||||
result.B=clamp(int(src.Z*255),0,255);
|
|
||||||
result.A=0xff;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BuildHeightmapNormals(int size,u16 *heightmap,CVector3D* normals)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
int sm=size-1;
|
|
||||||
|
|
||||||
for(y = 0;y < size; y++)
|
|
||||||
for(x = 0; x < size; x++) {
|
|
||||||
|
|
||||||
// Access current normalmap grid point
|
|
||||||
CVector3D* N = &normals[y*size+x];
|
|
||||||
|
|
||||||
// Compute normal by using the height differential
|
|
||||||
u16 h1=(x==sm) ? heightmap[y*size+x] : heightmap[y*size+x+1];
|
|
||||||
u16 h2=(y==sm) ? heightmap[y*size+x] : heightmap[(y+1)*size+x];
|
|
||||||
u16 h3=(x==0) ? heightmap[y*size+x] : heightmap[y*size+x-1];
|
|
||||||
u16 h4=(y==0) ? heightmap[y*size+x] : heightmap[(y-1)*size+x+1];
|
|
||||||
N->X = (h3-h1)*HEIGHT_SCALE;
|
|
||||||
N->Y = CELL_SIZE;
|
|
||||||
N->Z = (h4-h2)*HEIGHT_SCALE;
|
|
||||||
|
|
||||||
// Normalize it
|
|
||||||
float len=N->GetLength();
|
|
||||||
if (len>0) {
|
|
||||||
(*N)*=1.0f/len;
|
|
||||||
} else {
|
|
||||||
*N=CVector3D(0,0,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::BuildVertices()
|
|
||||||
{
|
|
||||||
// number of vertices in each direction in each patch
|
|
||||||
int vsize=PATCH_SIZE+1;
|
|
||||||
|
|
||||||
if (!m_Vertices) {
|
|
||||||
m_Vertices=new SBaseVertex[vsize*vsize];
|
|
||||||
}
|
|
||||||
SBaseVertex* vertices=m_Vertices;
|
|
||||||
|
|
||||||
|
|
||||||
// get index of this patch
|
|
||||||
u32 px=m_Patch->m_X;
|
|
||||||
u32 pz=m_Patch->m_Z;
|
|
||||||
|
|
||||||
CTerrain* terrain=m_Patch->m_Parent;
|
|
||||||
u32 mapSize=terrain->GetVerticesPerSide();
|
|
||||||
|
|
||||||
// build vertices
|
|
||||||
for (int j=0; j<vsize; j++)
|
|
||||||
{
|
|
||||||
for (int i=0; i<vsize; i++)
|
|
||||||
{
|
|
||||||
int ix=px*16+i;
|
|
||||||
int iz=pz*16+j;
|
|
||||||
|
|
||||||
CVector3D pos,normal;
|
|
||||||
terrain->CalcPosition(ix,iz,pos);
|
|
||||||
terrain->CalcNormal(ix,iz,normal);
|
|
||||||
|
|
||||||
RGBColor c;
|
|
||||||
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal,c);
|
|
||||||
|
|
||||||
int v=(j*vsize)+i;
|
|
||||||
vertices[v].m_UVs[0]=i*0.125f;
|
|
||||||
vertices[v].m_UVs[1]=j*0.125f;
|
|
||||||
vertices[v].m_Color=ConvertColor(c);
|
|
||||||
vertices[v].m_Position=pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
if (!m_VBBase) {
|
|
||||||
glGenBuffersARB(1,(GLuint*) &m_VBBase);
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBase);
|
|
||||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,vsize*vsize*sizeof(SBaseVertex),0,GL_STATIC_DRAW_ARB);
|
|
||||||
}
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBase);
|
|
||||||
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,0,vsize*vsize*sizeof(SBaseVertex),m_Vertices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::Build()
|
|
||||||
{
|
|
||||||
BuildVertices();
|
|
||||||
BuildIndices();
|
|
||||||
BuildBlends();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::Update()
|
|
||||||
{
|
|
||||||
if (m_UpdateFlags!=0) {
|
|
||||||
// TODO,RC 11/04/04 - need to only rebuild necessary bits of renderdata rather
|
|
||||||
// than everything; it's complicated slightly because the blends are dependent
|
|
||||||
// on both vertex and index data
|
|
||||||
BuildVertices();
|
|
||||||
BuildIndices();
|
|
||||||
BuildBlends();
|
|
||||||
|
|
||||||
m_UpdateFlags=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::RenderBase()
|
|
||||||
{
|
|
||||||
assert(m_UpdateFlags==0);
|
|
||||||
|
|
||||||
u8* base;
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBase);
|
|
||||||
base=0;
|
|
||||||
} else {
|
|
||||||
base=(u8*) &m_Vertices[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup data pointers
|
|
||||||
u32 stride=sizeof(SBaseVertex);
|
|
||||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_Position));
|
|
||||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBaseVertex,m_Color));
|
|
||||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBaseVertex,m_UVs[0]));
|
|
||||||
|
|
||||||
// render each splat
|
|
||||||
for (uint i=0;i<m_Splats.size();i++) {
|
|
||||||
SSplat& splat=m_Splats[i];
|
|
||||||
tex_bind(splat.m_Texture);
|
|
||||||
glDrawElements(GL_QUADS,splat.m_IndexCount,GL_UNSIGNED_SHORT,&m_Indices[splat.m_IndexStart]);
|
|
||||||
// bump stats
|
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
|
||||||
g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::RenderStreams(u32 streamflags)
|
|
||||||
{
|
|
||||||
assert(m_UpdateFlags==0);
|
|
||||||
|
|
||||||
u8* base;
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBase);
|
|
||||||
base=0;
|
|
||||||
} else {
|
|
||||||
base=(u8*) &m_Vertices[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup data pointers
|
|
||||||
glVertexPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position));
|
|
||||||
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_UVs));
|
|
||||||
|
|
||||||
// render all base splats at once
|
|
||||||
glDrawElements(GL_QUADS,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);
|
|
||||||
|
|
||||||
// bump stats
|
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
|
||||||
g_Renderer.m_Stats.m_TerrainTris+=(u32)m_Indices.size()/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CPatchRData::RenderBlends()
|
|
||||||
{
|
|
||||||
assert(m_UpdateFlags==0);
|
|
||||||
|
|
||||||
if (m_BlendVertices.size()==0) return;
|
|
||||||
|
|
||||||
u8* base;
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBlends);
|
|
||||||
base=0;
|
|
||||||
} else {
|
|
||||||
base=(u8*) &m_BlendVertices[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// setup data pointers
|
|
||||||
u32 stride=sizeof(SBlendVertex);
|
|
||||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
|
|
||||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color));
|
|
||||||
|
|
||||||
glClientActiveTexture(GL_TEXTURE0_ARB);
|
|
||||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
|
|
||||||
|
|
||||||
glClientActiveTexture(GL_TEXTURE1_ARB);
|
|
||||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_AlphaUVs[0]));
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
|
|
||||||
for (uint i=0;i<m_BlendSplats.size();i++) {
|
|
||||||
SSplat& splat=m_BlendSplats[i];
|
|
||||||
tex_bind(splat.m_Texture);
|
|
||||||
glDrawElements(GL_QUADS,splat.m_IndexCount,GL_UNSIGNED_SHORT,&m_BlendIndices[splat.m_IndexStart]);
|
|
||||||
|
|
||||||
// bump stats
|
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
|
||||||
g_Renderer.m_Stats.m_BlendSplats++;
|
|
||||||
g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPatchRData::RenderOutline()
|
|
||||||
{
|
|
||||||
const u16 EdgeIndices[PATCH_SIZE*4] = {
|
|
||||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
|
||||||
33, 50, 67, 84, 101, 118, 135, 152, 169, 186, 203, 220, 237, 254, 271, 288,
|
|
||||||
287, 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272,
|
|
||||||
255, 238, 221, 204, 187, 170, 153, 136, 119, 102, 85, 68, 51, 34, 17, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
u8* base;
|
|
||||||
if (g_Renderer.m_Caps.m_VBO) {
|
|
||||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VBBase);
|
|
||||||
base=0;
|
|
||||||
} else {
|
|
||||||
base=(u8*) &m_Vertices[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup data pointers
|
|
||||||
glVertexPointer(3,GL_FLOAT,sizeof(SBaseVertex),base+offsetof(SBaseVertex,m_Position));
|
|
||||||
// render outline as line loop
|
|
||||||
u32 numIndices=sizeof(EdgeIndices)/sizeof(u16);
|
|
||||||
glDrawElements(GL_LINE_LOOP,numIndices,GL_UNSIGNED_SHORT,EdgeIndices);
|
|
||||||
|
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
|
||||||
g_Renderer.m_Stats.m_TerrainTris+=numIndices/2;
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
#ifndef _PATCHRDATA_H
|
|
||||||
#define _PATCHRDATA_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "Color.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "RenderableObject.h"
|
|
||||||
|
|
||||||
class CPatch;
|
|
||||||
|
|
||||||
class CPatchRData : public CRenderData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPatchRData(CPatch* patch);
|
|
||||||
~CPatchRData();
|
|
||||||
|
|
||||||
void Update();
|
|
||||||
void RenderBase();
|
|
||||||
void RenderBlends();
|
|
||||||
void RenderOutline();
|
|
||||||
void RenderStreams(u32 streamflags);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// build this renderdata object
|
|
||||||
void Build();
|
|
||||||
|
|
||||||
void BuildBlends();
|
|
||||||
void BuildIndices();
|
|
||||||
void BuildVertices();
|
|
||||||
|
|
||||||
struct SSplat {
|
|
||||||
SSplat() : m_Texture(0), m_IndexCount(0) {}
|
|
||||||
|
|
||||||
// handle of texture to apply during splat
|
|
||||||
Handle m_Texture;
|
|
||||||
// offset into the index array for this patch where splat starts
|
|
||||||
u32 m_IndexStart;
|
|
||||||
// number of indices used by splat
|
|
||||||
u32 m_IndexCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SBaseVertex {
|
|
||||||
// vertex position
|
|
||||||
CVector3D m_Position;
|
|
||||||
// vertex color
|
|
||||||
SColor4ub m_Color;
|
|
||||||
// vertex uvs for base texture
|
|
||||||
float m_UVs[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SBlendVertex {
|
|
||||||
// vertex position
|
|
||||||
CVector3D m_Position;
|
|
||||||
// vertex color
|
|
||||||
SColor4ub m_Color;
|
|
||||||
// vertex uvs for base texture
|
|
||||||
float m_UVs[2];
|
|
||||||
// vertex uvs for alpha texture
|
|
||||||
float m_AlphaUVs[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct STex {
|
|
||||||
bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; }
|
|
||||||
bool operator<(const STex& rhs) const { return m_Priority<rhs.m_Priority; }
|
|
||||||
Handle m_Handle;
|
|
||||||
int m_Priority;
|
|
||||||
};
|
|
||||||
|
|
||||||
// owner patch
|
|
||||||
CPatch* m_Patch;
|
|
||||||
// vertex buffer handle for base vertices
|
|
||||||
u32 m_VBBase;
|
|
||||||
// vertex buffer handle for blend vertices
|
|
||||||
u32 m_VBBlends;
|
|
||||||
// patch render vertices
|
|
||||||
SBaseVertex* m_Vertices;
|
|
||||||
// patch index list
|
|
||||||
std::vector<unsigned short> m_Indices;
|
|
||||||
// list of base splats to apply to this patch
|
|
||||||
std::vector<SSplat> m_Splats;
|
|
||||||
// vertices to use for blending transition texture passes
|
|
||||||
std::vector<SBlendVertex> m_BlendVertices;
|
|
||||||
// indices into blend vertices for the blend splats
|
|
||||||
std::vector<unsigned short> m_BlendIndices;
|
|
||||||
// splats used in blend pass
|
|
||||||
std::vector<SSplat> m_BlendSplats;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,138 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Plane.Cpp
|
|
||||||
// Last Update: 17/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: A Plane in R3 and several utility methods.
|
|
||||||
// Note that the format used for the plane
|
|
||||||
// equation is Ax + By + Cz + D = 0, where
|
|
||||||
// <A,B,C> is the normal vector.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#include "Plane.h"
|
|
||||||
|
|
||||||
CPlane::CPlane ()
|
|
||||||
{
|
|
||||||
m_Norm.Clear ();
|
|
||||||
m_Dist = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sets the plane equation from 3 points on that plane
|
|
||||||
void CPlane::Set (CVector3D &p1, CVector3D &p2, CVector3D &p3)
|
|
||||||
{
|
|
||||||
CVector3D D1, D2;
|
|
||||||
CVector3D Norm;
|
|
||||||
|
|
||||||
//calculate two vectors on the surface of the plane
|
|
||||||
D1 = p2-p1;
|
|
||||||
D2 = p3-p1;
|
|
||||||
|
|
||||||
//cross multiply gives normal
|
|
||||||
Norm = D2.Cross(D1);
|
|
||||||
|
|
||||||
Set (Norm, p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//sets the plane equation from a normal and a point on
|
|
||||||
//that plane
|
|
||||||
void CPlane::Set (CVector3D &norm, CVector3D &point)
|
|
||||||
{
|
|
||||||
m_Norm = norm;
|
|
||||||
|
|
||||||
m_Dist = - (norm.X * point.X +
|
|
||||||
norm.Y * point.Y +
|
|
||||||
norm.Z * point.Z);
|
|
||||||
|
|
||||||
// Normalize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//normalizes the plane equation
|
|
||||||
void CPlane::Normalize ()
|
|
||||||
{
|
|
||||||
float Scale;
|
|
||||||
|
|
||||||
Scale = 1.0f/m_Norm.GetLength ();
|
|
||||||
|
|
||||||
m_Norm.X *= Scale;
|
|
||||||
m_Norm.Y *= Scale;
|
|
||||||
m_Norm.Z *= Scale;
|
|
||||||
m_Dist *= Scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns the side of the plane on which this point
|
|
||||||
//lies.
|
|
||||||
PLANESIDE CPlane::ClassifyPoint (const CVector3D &point) const
|
|
||||||
{
|
|
||||||
float Dist;
|
|
||||||
|
|
||||||
Dist = m_Norm.X * point.X +
|
|
||||||
m_Norm.Y * point.Y +
|
|
||||||
m_Norm.Z * point.Z +
|
|
||||||
m_Dist;
|
|
||||||
|
|
||||||
if (Dist > 0.0f)
|
|
||||||
return PS_FRONT;
|
|
||||||
else if (Dist < 0.0f)
|
|
||||||
return PS_BACK;
|
|
||||||
|
|
||||||
return PS_ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
//solves the plane equation for a particular point
|
|
||||||
float CPlane::DistanceToPlane (const CVector3D &point) const
|
|
||||||
{
|
|
||||||
float Dist;
|
|
||||||
|
|
||||||
Dist = m_Norm.X * point.X +
|
|
||||||
m_Norm.Y * point.Y +
|
|
||||||
m_Norm.Z * point.Z +
|
|
||||||
m_Dist;
|
|
||||||
|
|
||||||
return Dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculates the intersection point of a line with this
|
|
||||||
//plane. Returns false if there is no intersection
|
|
||||||
bool CPlane::FindLineSegIntersection (CVector3D &start, CVector3D &end, CVector3D *intsect)
|
|
||||||
{
|
|
||||||
PLANESIDE StartS, EndS;
|
|
||||||
CVector3D Dir;
|
|
||||||
float Length;
|
|
||||||
|
|
||||||
//work out where each point is
|
|
||||||
StartS = ClassifyPoint (start);
|
|
||||||
EndS = ClassifyPoint (end);
|
|
||||||
|
|
||||||
//if they are not on opposite sides of the plane return false
|
|
||||||
if (StartS == EndS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//work out a normalized vector in the direction start to end
|
|
||||||
Dir = end - start;
|
|
||||||
Dir.Normalize ();
|
|
||||||
|
|
||||||
//a bit of algebra to work out how much we need to scale
|
|
||||||
//this direction vector to get to the plane
|
|
||||||
Length = -m_Norm.Dot(start)/m_Norm.Dot(Dir);
|
|
||||||
|
|
||||||
//scale it by this amount
|
|
||||||
Dir *= Length;
|
|
||||||
|
|
||||||
//workout actual position vector of impact
|
|
||||||
*intsect = start + Dir;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CPlane::FindRayIntersection (CVector3D &start, CVector3D &direction, CVector3D *intsect)
|
|
||||||
{
|
|
||||||
float dot = m_Norm.Dot (direction);
|
|
||||||
if (dot == 0.0f)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CVector3D a;
|
|
||||||
*intsect = start - (direction * (DistanceToPlane (start)/dot));
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Plane.h
|
|
||||||
// Last Update: 17/2/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: A Plane in R3 and several utility methods.
|
|
||||||
// Note that the format used for the plane
|
|
||||||
// equation is Ax + By + Cz + D = 0, where
|
|
||||||
// <A,B,C> is the normal vector.
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef PLANE_H
|
|
||||||
#define PLANE_H
|
|
||||||
|
|
||||||
#include "Vector3D.h"
|
|
||||||
|
|
||||||
enum PLANESIDE
|
|
||||||
{
|
|
||||||
PS_FRONT,
|
|
||||||
PS_BACK,
|
|
||||||
PS_ON
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPlane
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CPlane ();
|
|
||||||
|
|
||||||
//sets the plane equation from 3 points on that plane
|
|
||||||
void Set (CVector3D &p1, CVector3D &p2, CVector3D &p3);
|
|
||||||
|
|
||||||
//sets the plane equation from a normal and a point on
|
|
||||||
//that plane
|
|
||||||
void Set (CVector3D &norm, CVector3D &point);
|
|
||||||
|
|
||||||
//normalizes the plane equation
|
|
||||||
void Normalize ();
|
|
||||||
|
|
||||||
//returns the side of the plane on which this point
|
|
||||||
//lies.
|
|
||||||
PLANESIDE ClassifyPoint (const CVector3D &point) const;
|
|
||||||
|
|
||||||
//solves the plane equation for a particular point
|
|
||||||
float DistanceToPlane (const CVector3D &point) const;
|
|
||||||
|
|
||||||
//calculates the intersection point of a line with this
|
|
||||||
//plane. Returns false if there is no intersection
|
|
||||||
bool FindLineSegIntersection (CVector3D &start, CVector3D &end, CVector3D *intsect);
|
|
||||||
bool FindRayIntersection (CVector3D &start, CVector3D &direction, CVector3D *intsect);
|
|
||||||
|
|
||||||
public:
|
|
||||||
CVector3D m_Norm; //normal vector of the plane
|
|
||||||
float m_Dist; //Plane distance (ie D in the plane eq.)
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,189 +0,0 @@
|
|||||||
/************************************************************
|
|
||||||
*
|
|
||||||
* File Name: Quaternion.Cpp
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
*
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
#include "Quaternion.h"
|
|
||||||
|
|
||||||
const float EPSILON=0.0001f;
|
|
||||||
|
|
||||||
|
|
||||||
CQuaternion::CQuaternion()
|
|
||||||
{
|
|
||||||
m_V.Clear ();
|
|
||||||
m_W = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//quaternion addition
|
|
||||||
CQuaternion CQuaternion::operator + (CQuaternion &quat)
|
|
||||||
{
|
|
||||||
CQuaternion Temp;
|
|
||||||
|
|
||||||
Temp.m_W = m_W + quat.m_W;
|
|
||||||
Temp.m_V = m_V + quat.m_V;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//quaternion addition/assignment
|
|
||||||
CQuaternion &CQuaternion::operator += (CQuaternion &quat)
|
|
||||||
{
|
|
||||||
m_W += quat.m_W;
|
|
||||||
m_V += quat.m_V;
|
|
||||||
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//quaternion multiplication
|
|
||||||
CQuaternion CQuaternion::operator * (CQuaternion &quat)
|
|
||||||
{
|
|
||||||
CQuaternion Temp;
|
|
||||||
|
|
||||||
Temp.m_W = (m_W * quat.m_W) - (m_V.Dot(quat.m_V));
|
|
||||||
Temp.m_V = (m_V.Cross(quat.m_V)) + (quat.m_V * m_W) + (m_V * quat.m_W);
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//quaternion multiplication/assignment
|
|
||||||
CQuaternion &CQuaternion::operator *= (CQuaternion &quat)
|
|
||||||
{
|
|
||||||
(*this) = (*this) * quat;
|
|
||||||
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CQuaternion::FromEularAngles (float x, float y, float z)
|
|
||||||
{
|
|
||||||
float cr, cp, cy;
|
|
||||||
float sr, sp, sy;
|
|
||||||
|
|
||||||
CQuaternion QRoll, QPitch, QYaw;
|
|
||||||
|
|
||||||
cr = cosf(x * 0.5f);
|
|
||||||
cp = cosf(y * 0.5f);
|
|
||||||
cy = cosf(z * 0.5f);
|
|
||||||
|
|
||||||
sr = sinf(x * 0.5f);
|
|
||||||
sp = sinf(y * 0.5f);
|
|
||||||
sy = sinf(z * 0.5f);
|
|
||||||
|
|
||||||
QRoll.m_V.Set (sr,0,0);
|
|
||||||
QRoll.m_W = cr;
|
|
||||||
|
|
||||||
QPitch.m_V.Set (0,sp,0);
|
|
||||||
QPitch.m_W = cp;
|
|
||||||
|
|
||||||
QYaw.m_V.Set (0,0,sy);
|
|
||||||
QYaw.m_W = cy;
|
|
||||||
|
|
||||||
(*this) = QYaw * QPitch * QRoll;
|
|
||||||
}
|
|
||||||
|
|
||||||
CMatrix3D CQuaternion::ToMatrix () const
|
|
||||||
{
|
|
||||||
CMatrix3D result;
|
|
||||||
ToMatrix(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CQuaternion::ToMatrix(CMatrix3D& result) const
|
|
||||||
{
|
|
||||||
float x2, y2, z2;
|
|
||||||
float wx, wy, wz, xx, xy, xz, yy, yz, zz;
|
|
||||||
|
|
||||||
// calculate coefficients
|
|
||||||
x2 = m_V.X + m_V.X;
|
|
||||||
y2 = m_V.Y + m_V.Y;
|
|
||||||
z2 = m_V.Z + m_V.Z;
|
|
||||||
|
|
||||||
xx = m_V.X * x2;
|
|
||||||
xy = m_V.X * y2;
|
|
||||||
xz = m_V.X * z2;
|
|
||||||
|
|
||||||
yy = m_V.Y * y2;
|
|
||||||
yz = m_V.Y * z2;
|
|
||||||
|
|
||||||
zz = m_V.Z * z2;
|
|
||||||
|
|
||||||
wx = m_W * x2;
|
|
||||||
wy = m_W * y2;
|
|
||||||
wz = m_W * z2;
|
|
||||||
|
|
||||||
result._11 = 1.0f - (yy + zz);
|
|
||||||
result._12 = xy - wz;
|
|
||||||
result._13 = xz + wy;
|
|
||||||
result._14 = 0;
|
|
||||||
|
|
||||||
result._21 = xy + wz;
|
|
||||||
result._22 = 1.0f - (xx + zz);
|
|
||||||
result._23 = yz - wx;
|
|
||||||
result._24 = 0;
|
|
||||||
|
|
||||||
result._31 = xz - wy;
|
|
||||||
result._32 = yz + wx;
|
|
||||||
result._33 = 1.0f - (xx + yy);
|
|
||||||
result._34 = 0;
|
|
||||||
|
|
||||||
result._41 = 0;
|
|
||||||
result._42 = 0;
|
|
||||||
result._43 = 0;
|
|
||||||
result._44 = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CQuaternion::Slerp(const CQuaternion& from,const CQuaternion& to, float ratio)
|
|
||||||
{
|
|
||||||
float to1[4];
|
|
||||||
float omega, cosom, sinom, scale0, scale1;
|
|
||||||
|
|
||||||
// calc cosine
|
|
||||||
cosom = from.m_V.X * to.m_V.X +
|
|
||||||
from.m_V.Y * to.m_V.Y +
|
|
||||||
from.m_V.Z * to.m_V.Z +
|
|
||||||
from.m_W * to.m_W;
|
|
||||||
|
|
||||||
|
|
||||||
// adjust signs (if necessary)
|
|
||||||
if (cosom < 0.0)
|
|
||||||
{
|
|
||||||
cosom = -cosom;
|
|
||||||
to1[0] = -to.m_V.X;
|
|
||||||
to1[1] = -to.m_V.Y;
|
|
||||||
to1[2] = -to.m_V.Z;
|
|
||||||
to1[3] = -to.m_W;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
to1[0] = to.m_V.X;
|
|
||||||
to1[1] = to.m_V.Y;
|
|
||||||
to1[2] = to.m_V.Z;
|
|
||||||
to1[3] = to.m_W;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate coefficients
|
|
||||||
if ((1.0f - cosom) > EPSILON)
|
|
||||||
{
|
|
||||||
// standard case (slerp)
|
|
||||||
omega = acosf(cosom);
|
|
||||||
sinom = sinf(omega);
|
|
||||||
scale0 = sinf((1.0f - ratio) * omega) / sinom;
|
|
||||||
scale1 = sinf(ratio * omega) / sinom;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// "from" and "to" quaternions are very close
|
|
||||||
// ... so we can do a linear interpolation
|
|
||||||
scale0 = 1.0f - ratio;
|
|
||||||
scale1 = ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate final values
|
|
||||||
m_V.X = scale0 * from.m_V.X + scale1 * to1[0];
|
|
||||||
m_V.Y = scale0 * from.m_V.Y + scale1 * to1[1];
|
|
||||||
m_V.Z = scale0 * from.m_V.Z + scale1 * to1[2];
|
|
||||||
m_W = scale0 * from.m_W + scale1 * to1[3];
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/************************************************************
|
|
||||||
*
|
|
||||||
* File Name: Quaternion.H
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
*
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
#ifndef QUATERNION_H
|
|
||||||
#define QUATERNION_H
|
|
||||||
|
|
||||||
#include "Matrix3D.h"
|
|
||||||
|
|
||||||
class CQuaternion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CVector3D m_V;
|
|
||||||
float m_W;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CQuaternion();
|
|
||||||
|
|
||||||
//quaternion addition
|
|
||||||
CQuaternion operator + (CQuaternion &quat);
|
|
||||||
//quaternion addition/assignment
|
|
||||||
CQuaternion &operator += (CQuaternion &quat);
|
|
||||||
|
|
||||||
//quaternion multiplication
|
|
||||||
CQuaternion operator * (CQuaternion &quat);
|
|
||||||
//quaternion multiplication/assignment
|
|
||||||
CQuaternion &operator *= (CQuaternion &quat);
|
|
||||||
|
|
||||||
void FromEularAngles (float x, float y, float z);
|
|
||||||
|
|
||||||
//convert the quaternion to matrix
|
|
||||||
CMatrix3D ToMatrix() const;
|
|
||||||
void ToMatrix(CMatrix3D& result) const;
|
|
||||||
|
|
||||||
//sphere interpolation
|
|
||||||
void Slerp(const CQuaternion& from,const CQuaternion& to, float ratio);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,94 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: RenderableObject.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _RENDERABLEOBJECT_H
|
|
||||||
#define _RENDERABLEOBJECT_H
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "terrain/Bound.h"
|
|
||||||
#include "terrain/Matrix3D.h"
|
|
||||||
|
|
||||||
|
|
||||||
// dirty flags - used as notification to the renderer that some bit of data
|
|
||||||
// need updating
|
|
||||||
#define RENDERDATA_UPDATE_VERTICES (1<<1)
|
|
||||||
#define RENDERDATA_UPDATE_INDICES (1<<2)
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CRenderData: base class of all the renderer's renderdata classes - the
|
|
||||||
// derived class stores necessary information for rendering an object of a
|
|
||||||
// particular type
|
|
||||||
class CRenderData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CRenderData() : m_UpdateFlags(0) {}
|
|
||||||
virtual ~CRenderData() {}
|
|
||||||
|
|
||||||
u32 m_UpdateFlags;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CRenderableObject: base class of all renderable objects - patches, models,
|
|
||||||
// sprites, etc; stores position and bound information, and a pointer to
|
|
||||||
// some renderdata necessary for the renderer to actually render it
|
|
||||||
class CRenderableObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor
|
|
||||||
CRenderableObject() : m_RenderData(0) {
|
|
||||||
m_Transform.SetIdentity();
|
|
||||||
}
|
|
||||||
// destructor
|
|
||||||
virtual ~CRenderableObject() { delete m_RenderData; }
|
|
||||||
|
|
||||||
// set object transform
|
|
||||||
void SetTransform(const CMatrix3D& transform) {
|
|
||||||
m_Transform=transform;
|
|
||||||
CalcBounds();
|
|
||||||
}
|
|
||||||
// get object transform
|
|
||||||
const CMatrix3D& GetTransform() const { return m_Transform; }
|
|
||||||
|
|
||||||
// mark some part of the renderdata as dirty, and requiring
|
|
||||||
// an update on next render
|
|
||||||
void SetDirty(u32 dirtyflags) {
|
|
||||||
if (m_RenderData) m_RenderData->m_UpdateFlags|=dirtyflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate (and store in m_Bounds) the world space bounds of this object
|
|
||||||
// - must be implemented by all concrete subclasses
|
|
||||||
virtual void CalcBounds() = 0;
|
|
||||||
|
|
||||||
// return world space bounds of this object
|
|
||||||
const CBound& GetBounds() const { return m_Bounds; }
|
|
||||||
|
|
||||||
// set the object renderdata
|
|
||||||
// TODO,RC 10/04/04 - need to delete existing renderdata here, or can we
|
|
||||||
// assume the renderer won't set renderdata when an object already has it?
|
|
||||||
// - just assert we've no renderdata at the minute
|
|
||||||
void SetRenderData(CRenderData* renderdata) {
|
|
||||||
assert(m_RenderData==0);
|
|
||||||
m_RenderData=renderdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return object renderdata - can be null if renderer hasn't yet
|
|
||||||
// created the renderdata
|
|
||||||
CRenderData* GetRenderData() { return m_RenderData; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// object bounds
|
|
||||||
CBound m_Bounds;
|
|
||||||
// local->world space transform
|
|
||||||
CMatrix3D m_Transform;
|
|
||||||
// object renderdata
|
|
||||||
CRenderData* m_RenderData;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,755 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Renderer.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: OpenGL renderer class; a higher level interface
|
|
||||||
// on top of OpenGL to handle rendering the basic visual games
|
|
||||||
// types - terrain, models, sprites, particles etc
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "TransparencyRenderer.h"
|
|
||||||
#include "Terrain.h"
|
|
||||||
#include "Matrix3D.h"
|
|
||||||
#include "Camera.h"
|
|
||||||
#include "PatchRData.h"
|
|
||||||
#include "Texture.h"
|
|
||||||
#include "LightEnv.h"
|
|
||||||
|
|
||||||
#include "Model.h"
|
|
||||||
#include "ModelDef.h"
|
|
||||||
|
|
||||||
#include "ogl.h"
|
|
||||||
#include "res/mem.h"
|
|
||||||
#include "res/tex.h"
|
|
||||||
|
|
||||||
struct TGAHeader {
|
|
||||||
// header stuff
|
|
||||||
unsigned char iif_size;
|
|
||||||
unsigned char cmap_type;
|
|
||||||
unsigned char image_type;
|
|
||||||
unsigned char pad[5];
|
|
||||||
|
|
||||||
// origin : unused
|
|
||||||
unsigned short d_x_origin;
|
|
||||||
unsigned short d_y_origin;
|
|
||||||
|
|
||||||
// dimensions
|
|
||||||
unsigned short width;
|
|
||||||
unsigned short height;
|
|
||||||
|
|
||||||
// bits per pixel : 16, 24 or 32
|
|
||||||
unsigned char bpp;
|
|
||||||
|
|
||||||
// image descriptor : Bits 3-0: size of alpha channel
|
|
||||||
// Bit 4: must be 0 (reserved)
|
|
||||||
// Bit 5: should be 0 (origin)
|
|
||||||
// Bits 6-7: should be 0 (interleaving)
|
|
||||||
unsigned char image_descriptor;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool saveTGA(const char* filename,int width,int height,unsigned char* data)
|
|
||||||
{
|
|
||||||
FILE* fp=fopen(filename,"wb");
|
|
||||||
if (!fp) return false;
|
|
||||||
|
|
||||||
// fill file header
|
|
||||||
TGAHeader header;
|
|
||||||
header.iif_size=0;
|
|
||||||
header.cmap_type=0;
|
|
||||||
header.image_type=2;
|
|
||||||
memset(header.pad,0,sizeof(header.pad));
|
|
||||||
header.d_x_origin=0;
|
|
||||||
header.d_y_origin=0;
|
|
||||||
header.width=width;
|
|
||||||
header.height=height;
|
|
||||||
header.bpp=24;
|
|
||||||
header.image_descriptor=0;
|
|
||||||
|
|
||||||
if (fwrite(&header,sizeof(TGAHeader),1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write data
|
|
||||||
if (fwrite(data,width*height*3,1,fp)!=1) {
|
|
||||||
fclose(fp);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return success ..
|
|
||||||
fclose(fp);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern CTerrain g_Terrain;
|
|
||||||
|
|
||||||
|
|
||||||
CRenderer::CRenderer ()
|
|
||||||
{
|
|
||||||
m_Width=0;
|
|
||||||
m_Height=0;
|
|
||||||
m_Depth=0;
|
|
||||||
m_FrameCounter=0;
|
|
||||||
m_TerrainRenderMode=SOLID;
|
|
||||||
m_ModelRenderMode=SOLID;
|
|
||||||
m_ClearColor[0]=m_ClearColor[1]=m_ClearColor[2]=m_ClearColor[3]=0;
|
|
||||||
m_OptNOVBO=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRenderer::~CRenderer ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// EnumCaps: build card cap bits
|
|
||||||
void CRenderer::EnumCaps()
|
|
||||||
{
|
|
||||||
// assume support for nothing
|
|
||||||
m_Caps.m_VBO=false;
|
|
||||||
|
|
||||||
// now start querying extensions
|
|
||||||
if (!m_OptNOVBO) {
|
|
||||||
if (oglExtAvail("GL_ARB_vertex_buffer_object")) {
|
|
||||||
m_Caps.m_VBO=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRenderer::Open(int width, int height, int depth)
|
|
||||||
{
|
|
||||||
m_Width = width;
|
|
||||||
m_Height = height;
|
|
||||||
m_Depth = depth;
|
|
||||||
|
|
||||||
// set packing parameters
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT,1);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
|
|
||||||
|
|
||||||
// setup default state
|
|
||||||
glDepthFunc(GL_LEQUAL);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glCullFace(GL_BACK);
|
|
||||||
glFrontFace(GL_CCW);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glClearColor(0.0f,0.0f,0.0f,0.0f);
|
|
||||||
|
|
||||||
// query card capabilities
|
|
||||||
EnumCaps();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Close()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// resize renderer view
|
|
||||||
void CRenderer::Resize(int width,int height)
|
|
||||||
{
|
|
||||||
m_Width = width;
|
|
||||||
m_Height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SetOption: set boolean renderer option
|
|
||||||
void CRenderer::SetOption(enum Option opt,bool value)
|
|
||||||
{
|
|
||||||
switch (opt) {
|
|
||||||
case OPT_NOVBO:
|
|
||||||
m_OptNOVBO=value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// BeginFrame: signal frame start
|
|
||||||
void CRenderer::BeginFrame()
|
|
||||||
{
|
|
||||||
// bump frame counter
|
|
||||||
m_FrameCounter++;
|
|
||||||
|
|
||||||
// zero out all the per-frame stats
|
|
||||||
m_Stats.Reset();
|
|
||||||
|
|
||||||
// calculate coefficients for terrain and unit lighting
|
|
||||||
m_SHCoeffsUnits.Clear();
|
|
||||||
m_SHCoeffsTerrain.Clear();
|
|
||||||
|
|
||||||
if (m_LightEnv) {
|
|
||||||
CVector3D dirlight;
|
|
||||||
m_LightEnv->GetSunDirection(dirlight);
|
|
||||||
m_SHCoeffsUnits.AddDirectionalLight(dirlight,m_LightEnv->m_SunColor);
|
|
||||||
m_SHCoeffsTerrain.AddDirectionalLight(dirlight,m_LightEnv->m_SunColor);
|
|
||||||
|
|
||||||
m_SHCoeffsUnits.AddAmbientLight(m_LightEnv->m_UnitsAmbientColor);
|
|
||||||
m_SHCoeffsTerrain.AddAmbientLight(m_LightEnv->m_TerrainAmbientColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear buffers
|
|
||||||
glClearColor(m_ClearColor[0],m_ClearColor[1],m_ClearColor[2],m_ClearColor[3]);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SetClearColor: set color used to clear screen in BeginFrame()
|
|
||||||
void CRenderer::SetClearColor(u32 color)
|
|
||||||
{
|
|
||||||
m_ClearColor[0]=float(color & 0xff)/255.0f;
|
|
||||||
m_ClearColor[1]=float((color>>8) & 0xff)/255.0f;
|
|
||||||
m_ClearColor[2]=float((color>>16) & 0xff)/255.0f;
|
|
||||||
m_ClearColor[3]=float((color>>24) & 0xff)/255.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int RoundUpToPowerOf2(int x)
|
|
||||||
{
|
|
||||||
if ((x & (x-1))==0) return x;
|
|
||||||
int d=x;
|
|
||||||
while (d & (d-1)) {
|
|
||||||
d&=(d-1);
|
|
||||||
}
|
|
||||||
return d<<1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CRenderer::RenderPatches()
|
|
||||||
{
|
|
||||||
// switch on wireframe if we need it
|
|
||||||
if (m_TerrainRenderMode==WIREFRAME) {
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// render all the patches, including blend pass
|
|
||||||
RenderPatchSubmissions();
|
|
||||||
|
|
||||||
if (m_TerrainRenderMode==WIREFRAME) {
|
|
||||||
// switch wireframe off again
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
} else if (m_TerrainRenderMode==EDGED_FACES) {
|
|
||||||
// edged faces: need to make a second pass over the data:
|
|
||||||
// first switch on wireframe
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
|
|
||||||
// setup some renderstate ..
|
|
||||||
glDepthMask(0);
|
|
||||||
SetTexture(0,0);
|
|
||||||
glColor4f(1,1,1,0.35f);
|
|
||||||
glLineWidth(2.0f);
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// .. and some client states
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
// render each patch in wireframe
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
CPatch* patch=m_TerrainPatches[i];
|
|
||||||
CPatchRData* patchdata=(CPatchRData*) patch->GetRenderData();
|
|
||||||
patchdata->RenderStreams(STREAM_POS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set color for outline
|
|
||||||
glColor3f(0,0,1);
|
|
||||||
glLineWidth(4.0f);
|
|
||||||
|
|
||||||
// render outline of each patch
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
CPatch* patch=m_TerrainPatches[i];
|
|
||||||
CPatchRData* patchdata=(CPatchRData*) patch->GetRenderData();
|
|
||||||
patchdata->RenderOutline();
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. and switch off the client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
// .. and restore the renderstates
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glDepthMask(1);
|
|
||||||
|
|
||||||
// restore fill mode, and we're done
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::RenderModelSubmissions()
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
// build up transparent passes
|
|
||||||
for (i=0;i<m_Models.size();++i) {
|
|
||||||
BuildTransparentPasses(m_Models[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup texture environment to modulate diffuse color with texture color
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
// just pass through texture's alpha
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
||||||
|
|
||||||
// setup client states
|
|
||||||
glClientActiveTexture(GL_TEXTURE0);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// render models
|
|
||||||
for (i=0;i<m_Models.size();++i) {
|
|
||||||
CModel* model=m_Models[i];
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
modeldata->RenderStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0,model->GetTransform());
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch off client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::RenderModels()
|
|
||||||
{
|
|
||||||
// switch on wireframe if we need it
|
|
||||||
if (m_ModelRenderMode==WIREFRAME) {
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// render all the models
|
|
||||||
RenderModelSubmissions();
|
|
||||||
|
|
||||||
if (m_ModelRenderMode==WIREFRAME) {
|
|
||||||
// switch wireframe off again
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
} else if (m_ModelRenderMode==EDGED_FACES) {
|
|
||||||
// edged faces: need to make a second pass over the data:
|
|
||||||
// first switch on wireframe
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
|
|
||||||
// setup some renderstate ..
|
|
||||||
glDepthMask(0);
|
|
||||||
SetTexture(0,0);
|
|
||||||
glColor4f(1,1,1,0.75f);
|
|
||||||
glLineWidth(1.0f);
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// .. and some client states
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
// render each model
|
|
||||||
for (uint i=0;i<m_Models.size();++i) {
|
|
||||||
CModel* model=m_Models[i];
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
modeldata->RenderStreams(STREAM_POS,model->GetTransform());
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. and switch off the client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
// .. and restore the renderstates
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glDepthMask(1);
|
|
||||||
|
|
||||||
// restore fill mode, and we're done
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// FlushFrame: force rendering of any batched objects
|
|
||||||
void CRenderer::FlushFrame()
|
|
||||||
{
|
|
||||||
// update renderdata of everything submitted
|
|
||||||
UpdateSubmittedObjectData();
|
|
||||||
|
|
||||||
// render submitted patches and models
|
|
||||||
RenderPatches();
|
|
||||||
RenderModels();
|
|
||||||
|
|
||||||
// call on the transparency renderer to render all the transparent stuff
|
|
||||||
g_TransparencyRenderer.Render();
|
|
||||||
|
|
||||||
// empty lists
|
|
||||||
m_TerrainPatches.clear();
|
|
||||||
m_Models.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// signal frame end : implicitly flushes batched objects
|
|
||||||
void CRenderer::EndFrame()
|
|
||||||
{
|
|
||||||
FlushFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::SetCamera(CCamera& camera)
|
|
||||||
{
|
|
||||||
CMatrix3D view;
|
|
||||||
camera.m_Orientation.GetInverse(view);
|
|
||||||
CMatrix3D proj = camera.GetProjection();
|
|
||||||
|
|
||||||
float gl_view[16] = {view._11, view._21, view._31, view._41,
|
|
||||||
view._12, view._22, view._32, view._42,
|
|
||||||
view._13, view._23, view._33, view._43,
|
|
||||||
view._14, view._24, view._34, view._44};
|
|
||||||
|
|
||||||
float gl_proj[16] = {proj._11, proj._21, proj._31, proj._41,
|
|
||||||
proj._12, proj._22, proj._32, proj._42,
|
|
||||||
proj._13, proj._23, proj._33, proj._43,
|
|
||||||
proj._14, proj._24, proj._34, proj._44};
|
|
||||||
|
|
||||||
|
|
||||||
glMatrixMode (GL_PROJECTION);
|
|
||||||
glLoadMatrixf (gl_proj);
|
|
||||||
|
|
||||||
glMatrixMode (GL_MODELVIEW);
|
|
||||||
glLoadMatrixf (gl_view);
|
|
||||||
|
|
||||||
const SViewPort& vp = camera.GetViewPort();
|
|
||||||
glViewport (vp.m_X, vp.m_Y, vp.m_Width, vp.m_Height);
|
|
||||||
|
|
||||||
m_Camera=camera;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Submit(CPatch* patch)
|
|
||||||
{
|
|
||||||
m_TerrainPatches.push_back(patch);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Submit(CModel* model)
|
|
||||||
{
|
|
||||||
m_Models.push_back(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Submit(CSprite* sprite)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Submit(CParticleSys* psys)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::Submit(COverlay* overlay)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::RenderPatchSubmissions()
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
// set up client states for base pass
|
|
||||||
glClientActiveTexture(GL_TEXTURE0);
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// set up texture environment for base pass
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_ZERO);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// render base passes for each patch
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
CPatch* patch=m_TerrainPatches[i];
|
|
||||||
CPatchRData* patchdata=(CPatchRData*) patch->GetRenderData();
|
|
||||||
patchdata->RenderBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch on the composite alpha map texture
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D,m_CompositeAlphaMap);
|
|
||||||
|
|
||||||
// setup additional texenv required by blend pass
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// switch on blending
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// no need to write to the depth buffer a second time
|
|
||||||
glDepthMask(0);
|
|
||||||
|
|
||||||
glClientActiveTexture(GL_TEXTURE1);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// render blend passes for each patch
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
CPatch* patch=m_TerrainPatches[i];
|
|
||||||
CPatchRData* patchdata=(CPatchRData*) patch->GetRenderData();
|
|
||||||
patchdata->RenderBlends();
|
|
||||||
}
|
|
||||||
|
|
||||||
glClientActiveTexture(GL_TEXTURE1);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// restore depth writes
|
|
||||||
glDepthMask(1);
|
|
||||||
|
|
||||||
// restore default state: switch off blending
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
|
|
||||||
// switch off texture unit 1, make unit 0 active texture
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
// switch off all client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glClientActiveTexture(GL_TEXTURE0);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// try and load the given texture
|
|
||||||
bool CRenderer::LoadTexture(CTexture* texture)
|
|
||||||
{
|
|
||||||
Handle h=texture->GetHandle();
|
|
||||||
if (h) {
|
|
||||||
// already tried to load this texture, nothing to do here - just return success according
|
|
||||||
// to whether this is a valid handle or not
|
|
||||||
return h==0xfffffff ? true : false;
|
|
||||||
} else {
|
|
||||||
h=tex_load(texture->GetName());
|
|
||||||
if (h <= 0) {
|
|
||||||
texture->SetHandle(0xffffffff);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
tex_upload(h);
|
|
||||||
|
|
||||||
tex_bind(h);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
texture->SetHandle(h);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
|
||||||
void CRenderer::SetTexture(int unit,CTexture* texture,u32 wrapflags)
|
|
||||||
{
|
|
||||||
glActiveTexture(GL_TEXTURE0+unit);
|
|
||||||
if (texture) {
|
|
||||||
Handle h=texture->GetHandle();
|
|
||||||
if (!h) {
|
|
||||||
LoadTexture(texture);
|
|
||||||
h=texture->GetHandle();
|
|
||||||
|
|
||||||
if (wrapflags) {
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapflags);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapflags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// disable texturing if invalid handle
|
|
||||||
if (h==0xffffffff) {
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
} else {
|
|
||||||
tex_bind(h);
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// switch off texturing on this unit
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRenderer::IsTextureTransparent(CTexture* texture)
|
|
||||||
{
|
|
||||||
if (texture) {
|
|
||||||
Handle h=texture->GetHandle();
|
|
||||||
if (!h) {
|
|
||||||
LoadTexture(texture);
|
|
||||||
h=texture->GetHandle();
|
|
||||||
}
|
|
||||||
if (h!=0xffffffff && h) {
|
|
||||||
int fmt;
|
|
||||||
int bpp;
|
|
||||||
|
|
||||||
tex_info(h, NULL, NULL, &fmt, &bpp, NULL);
|
|
||||||
if (bpp==24 || fmt == GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void CopyTriple(unsigned char* dst,const unsigned char* src)
|
|
||||||
{
|
|
||||||
dst[0]=src[0];
|
|
||||||
dst[1]=src[1];
|
|
||||||
dst[2]=src[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAlphaMaps: load the 14 default alpha maps, pack them into one composite texture and
|
|
||||||
// calculate the coordinate of each alphamap within this packed texture .. need to add
|
|
||||||
// validation that all maps are the same size
|
|
||||||
bool CRenderer::LoadAlphaMaps(const char* fnames[])
|
|
||||||
{
|
|
||||||
glActiveTexture(GL_TEXTURE0_ARB);
|
|
||||||
|
|
||||||
Handle textures[NumAlphaMaps];
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=0;i<NumAlphaMaps;i++) {
|
|
||||||
textures[i]=tex_load(fnames[i]);
|
|
||||||
if (textures[i] <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int base;
|
|
||||||
|
|
||||||
i=tex_info(textures[0], &base, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
int size=(base+4)*NumAlphaMaps;
|
|
||||||
int texsize=RoundUpToPowerOf2(size);
|
|
||||||
|
|
||||||
unsigned char* data=new unsigned char[texsize*base*3];
|
|
||||||
|
|
||||||
// for each tile on row
|
|
||||||
for (i=0;i<NumAlphaMaps;i++) {
|
|
||||||
|
|
||||||
int bpp;
|
|
||||||
// get src of copy
|
|
||||||
const u8* src;
|
|
||||||
|
|
||||||
tex_info(textures[i], NULL, NULL, NULL, &bpp, (void **)&src);
|
|
||||||
|
|
||||||
int srcstep=bpp/8;
|
|
||||||
|
|
||||||
// get destination of copy
|
|
||||||
u8* dst=data+3*(i*(base+4));
|
|
||||||
|
|
||||||
// for each row of image
|
|
||||||
for (int j=0;j<base;j++) {
|
|
||||||
// duplicate first pixel
|
|
||||||
CopyTriple(dst,src);
|
|
||||||
dst+=3;
|
|
||||||
CopyTriple(dst,src);
|
|
||||||
dst+=3;
|
|
||||||
|
|
||||||
// copy a row
|
|
||||||
for (int k=0;k<base;k++) {
|
|
||||||
CopyTriple(dst,src);
|
|
||||||
dst+=3;
|
|
||||||
src+=srcstep;
|
|
||||||
}
|
|
||||||
// duplicate last pixel
|
|
||||||
CopyTriple(dst,(src-srcstep));
|
|
||||||
dst+=3;
|
|
||||||
CopyTriple(dst,(src-srcstep));
|
|
||||||
dst+=3;
|
|
||||||
|
|
||||||
// advance write pointer for next row
|
|
||||||
dst+=3*(texsize-(base+4));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_AlphaMapCoords[i].u0=float(i*(base+4)+2)/float(texsize);
|
|
||||||
m_AlphaMapCoords[i].u1=float((i+1)*(base+4)-2)/float(texsize);
|
|
||||||
m_AlphaMapCoords[i].v0=0.0f;
|
|
||||||
m_AlphaMapCoords[i].v1=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenTextures(1,(GLuint*) &m_CompositeAlphaMap);
|
|
||||||
glBindTexture(GL_TEXTURE_2D,m_CompositeAlphaMap);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,texsize,base,0,GL_RGB,GL_UNSIGNED_BYTE,data);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
delete[] data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRenderer::BuildTransparentPasses(CModel* model)
|
|
||||||
{
|
|
||||||
if (!IsTextureTransparent(model->GetTexture())) {
|
|
||||||
// ok, no transparency on this model .. ignore it here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add this visual to the transparency renderer for later processing
|
|
||||||
g_TransparencyRenderer.Add(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// UpdateSubmittedObjectData: ensure all submitted objects have renderdata and that it is up to date
|
|
||||||
// - call once before doing anything with any objects
|
|
||||||
void CRenderer::UpdateSubmittedObjectData()
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
// ensure all patches have up to date renderdata built for them
|
|
||||||
for (i=0;i<m_TerrainPatches.size();++i) {
|
|
||||||
CPatch* patch=m_TerrainPatches[i];
|
|
||||||
CPatchRData* data=(CPatchRData*) patch->GetRenderData();
|
|
||||||
if (data==0) {
|
|
||||||
// no renderdata for patch, create it now
|
|
||||||
data=new CPatchRData(patch);
|
|
||||||
patch->SetRenderData(data);
|
|
||||||
} else {
|
|
||||||
data->Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure all models have up to date renderdata built for them
|
|
||||||
for (i=0;i<m_Models.size();++i) {
|
|
||||||
CModel* model=m_Models[i];
|
|
||||||
CModelRData* data=(CModelRData*) model->GetRenderData();
|
|
||||||
if (data==0) {
|
|
||||||
// no renderdata for model, create it now
|
|
||||||
data=new CModelRData(model);
|
|
||||||
model->SetRenderData(data);
|
|
||||||
} else {
|
|
||||||
data->Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,267 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Renderer.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: OpenGL renderer class; a higher level interface
|
|
||||||
// on top of OpenGL to handle rendering the basic visual games
|
|
||||||
// types - terrain, models, sprites, particles etc
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef RENDERER_H
|
|
||||||
#define RENDERER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "ogl.h"
|
|
||||||
#include "Camera.h"
|
|
||||||
#include "Frustum.h"
|
|
||||||
#include "PatchRData.h"
|
|
||||||
#include "ModelRData.h"
|
|
||||||
#include "SHCoeffs.h"
|
|
||||||
#include "Terrain.h"
|
|
||||||
|
|
||||||
// necessary declarations
|
|
||||||
class CCamera;
|
|
||||||
class CPatch;
|
|
||||||
class CSprite;
|
|
||||||
class CParticleSys;
|
|
||||||
class COverlay;
|
|
||||||
class CMaterial;
|
|
||||||
class CLightEnv;
|
|
||||||
class CTexture;
|
|
||||||
class CTerrain;
|
|
||||||
|
|
||||||
|
|
||||||
// rendering modes
|
|
||||||
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
|
|
||||||
|
|
||||||
// stream flags
|
|
||||||
#define STREAM_POS 0x01
|
|
||||||
#define STREAM_NORMAL 0x02
|
|
||||||
#define STREAM_COLOR 0x04
|
|
||||||
#define STREAM_UV0 0x08
|
|
||||||
#define STREAM_UV1 0x10
|
|
||||||
#define STREAM_UV2 0x20
|
|
||||||
#define STREAM_UV3 0x40
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SVertex3D: simple 3D vertex declaration
|
|
||||||
struct SVertex3D
|
|
||||||
{
|
|
||||||
float m_Position[3];
|
|
||||||
float m_TexCoords[2];
|
|
||||||
unsigned int m_Color;
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SVertex2D: simple 2D vertex declaration
|
|
||||||
struct SVertex2D
|
|
||||||
{
|
|
||||||
float m_Position[2];
|
|
||||||
float m_TexCoords[2];
|
|
||||||
unsigned int m_Color;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CRenderer: base renderer class - primary interface to the rendering engine
|
|
||||||
class CRenderer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// various enumerations and renderer related constants
|
|
||||||
enum { NumAlphaMaps=14 };
|
|
||||||
enum Option {
|
|
||||||
OPT_NOVBO
|
|
||||||
};
|
|
||||||
|
|
||||||
// stats class - per frame counts of number of draw calls, poly counts etc
|
|
||||||
struct Stats {
|
|
||||||
// set all stats to zero
|
|
||||||
void Reset() { memset(this,0,sizeof(*this)); }
|
|
||||||
// add given stats to this stats
|
|
||||||
Stats& operator+=(const Stats& rhs) {
|
|
||||||
m_Counter++;
|
|
||||||
m_DrawCalls+=rhs.m_DrawCalls;
|
|
||||||
m_TerrainTris+=rhs.m_TerrainTris;
|
|
||||||
m_ModelTris+=rhs.m_ModelTris;
|
|
||||||
m_TransparentTris+=rhs.m_TransparentTris;
|
|
||||||
m_BlendSplats+=rhs.m_BlendSplats;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
// count of the number of stats added together
|
|
||||||
u32 m_Counter;
|
|
||||||
// number of draw calls per frame - total DrawElements + Begin/End immediate mode loops
|
|
||||||
u32 m_DrawCalls;
|
|
||||||
// number of terrain triangles drawn
|
|
||||||
u32 m_TerrainTris;
|
|
||||||
// number of (non-transparent) model triangles drawn
|
|
||||||
u32 m_ModelTris;
|
|
||||||
// number of transparent model triangles drawn
|
|
||||||
u32 m_TransparentTris;
|
|
||||||
// number of splat passes for alphamapping
|
|
||||||
u32 m_BlendSplats;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// constructor, destructor
|
|
||||||
CRenderer();
|
|
||||||
~CRenderer();
|
|
||||||
|
|
||||||
// open up the renderer: performs any necessary initialisation
|
|
||||||
bool Open(int width,int height,int depth);
|
|
||||||
// shutdown the renderer: performs any necessary cleanup
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
// resize renderer view
|
|
||||||
void Resize(int width,int height);
|
|
||||||
|
|
||||||
// set boolean renderer option
|
|
||||||
void SetOption(enum Option opt,bool value);
|
|
||||||
|
|
||||||
// return view width
|
|
||||||
int GetWidth() const { return m_Width; }
|
|
||||||
// return view height
|
|
||||||
int GetHeight() const { return m_Height; }
|
|
||||||
// return view aspect ratio
|
|
||||||
float GetAspect() const { return float(m_Width)/float(m_Height); }
|
|
||||||
|
|
||||||
// signal frame start
|
|
||||||
void BeginFrame();
|
|
||||||
// force rendering of any batched objects
|
|
||||||
void FlushFrame();
|
|
||||||
// signal frame end : implicitly flushes batched objects
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
// set color used to clear screen in BeginFrame()
|
|
||||||
void SetClearColor(u32 color);
|
|
||||||
|
|
||||||
// return current frame counter
|
|
||||||
int GetFrameCounter() const { return m_FrameCounter; }
|
|
||||||
|
|
||||||
// set camera used for subsequent rendering operations; includes viewport, projection and modelview matrices
|
|
||||||
void SetCamera(CCamera& camera);
|
|
||||||
|
|
||||||
// submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond
|
|
||||||
// the call to frame end, as must the object itself
|
|
||||||
void Submit(CPatch* patch);
|
|
||||||
void Submit(CModel* model);
|
|
||||||
void Submit(CSprite* sprite);
|
|
||||||
void Submit(CParticleSys* psys);
|
|
||||||
void Submit(COverlay* overlay);
|
|
||||||
|
|
||||||
// basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in
|
|
||||||
// editor tools (eg for highlighting specific terrain patches)
|
|
||||||
// note:
|
|
||||||
// * all 3D vertices specified in world space
|
|
||||||
// * primitive operations rendered immediatedly, never batched
|
|
||||||
// * primitives rendered in current material (set via SetMaterial)
|
|
||||||
void RenderLine(const SVertex2D* vertices);
|
|
||||||
void RenderLineLoop(int len,const SVertex2D* vertices);
|
|
||||||
void RenderTri(const SVertex2D* vertices);
|
|
||||||
void RenderQuad(const SVertex2D* vertices);
|
|
||||||
void RenderLine(const SVertex3D* vertices);
|
|
||||||
void RenderLineLoop(int len,const SVertex3D* vertices);
|
|
||||||
void RenderTri(const SVertex3D* vertices);
|
|
||||||
void RenderQuad(const SVertex3D* vertices);
|
|
||||||
|
|
||||||
// set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer,
|
|
||||||
// so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering)
|
|
||||||
void SetLightEnv(CLightEnv* lightenv) {
|
|
||||||
m_LightEnv=lightenv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the mode to render subsequent terrain patches
|
|
||||||
void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; }
|
|
||||||
// get the mode to render subsequent terrain patches
|
|
||||||
ERenderMode GetTerrainRenderMode() const { return m_TerrainRenderMode; }
|
|
||||||
|
|
||||||
// set the mode to render subsequent models
|
|
||||||
void SetModelRenderMode(ERenderMode mode) { m_ModelRenderMode=mode; }
|
|
||||||
// get the mode to render subsequent models
|
|
||||||
ERenderMode GetModelRenderMode() const { return m_ModelRenderMode; }
|
|
||||||
|
|
||||||
// try and load the given texture
|
|
||||||
bool LoadTexture(CTexture* texture);
|
|
||||||
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
|
||||||
// note - active texture always set to given unit on exit
|
|
||||||
void SetTexture(int unit,CTexture* texture,u32 wrapflags=0);
|
|
||||||
// query transparency of given texture
|
|
||||||
bool IsTextureTransparent(CTexture* texture);
|
|
||||||
|
|
||||||
// load the default set of alphamaps; return false if any alphamap fails to load, true otherwise
|
|
||||||
bool LoadAlphaMaps(const char* fnames[]);
|
|
||||||
|
|
||||||
// return stats accumulated for current frame
|
|
||||||
const Stats& GetStats() { return m_Stats; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class CPatchRData;
|
|
||||||
friend class CModelRData;
|
|
||||||
friend class CTransparencyRenderer;
|
|
||||||
|
|
||||||
// update renderdata of everything submitted
|
|
||||||
void UpdateSubmittedObjectData();
|
|
||||||
|
|
||||||
// patch rendering stuff
|
|
||||||
void RenderPatchSubmissions();
|
|
||||||
void RenderPatches();
|
|
||||||
|
|
||||||
// model rendering stuff
|
|
||||||
void BuildTransparentPasses(CModel* model);
|
|
||||||
void RenderModelSubmissions();
|
|
||||||
void RenderModels();
|
|
||||||
|
|
||||||
// RENDERER DATA:
|
|
||||||
// view width
|
|
||||||
int m_Width;
|
|
||||||
// view height
|
|
||||||
int m_Height;
|
|
||||||
// view depth (bpp)
|
|
||||||
int m_Depth;
|
|
||||||
// frame counter
|
|
||||||
int m_FrameCounter;
|
|
||||||
// current terrain rendering mode
|
|
||||||
ERenderMode m_TerrainRenderMode;
|
|
||||||
// current model rendering mode
|
|
||||||
ERenderMode m_ModelRenderMode;
|
|
||||||
// current view camera
|
|
||||||
CCamera m_Camera;
|
|
||||||
// color used to clear screen in BeginFrame
|
|
||||||
float m_ClearColor[4];
|
|
||||||
// submitted object lists for batching
|
|
||||||
std::vector<CPatch*> m_TerrainPatches;
|
|
||||||
std::vector<CModel*> m_Models;
|
|
||||||
std::vector<CSprite*> m_Sprites;
|
|
||||||
std::vector<CParticleSys*> m_ParticleSyses;
|
|
||||||
std::vector<COverlay*> m_Overlays;
|
|
||||||
// current lighting setup
|
|
||||||
CLightEnv* m_LightEnv;
|
|
||||||
// current spherical harmonic coefficients (for unit lighting), derived from lightenv
|
|
||||||
CSHCoeffs m_SHCoeffsUnits;
|
|
||||||
// current spherical harmonic coefficients (for terrain lighting), derived from lightenv
|
|
||||||
CSHCoeffs m_SHCoeffsTerrain;
|
|
||||||
// handle of composite alpha map (all the alpha maps packed into one texture)
|
|
||||||
u32 m_CompositeAlphaMap;
|
|
||||||
// coordinates of each (untransformed) alpha map within the packed texture
|
|
||||||
struct {
|
|
||||||
float u0,u1,v0,v1;
|
|
||||||
} m_AlphaMapCoords[NumAlphaMaps];
|
|
||||||
// renderer options
|
|
||||||
bool m_OptNOVBO;
|
|
||||||
// card capabilities
|
|
||||||
struct Caps {
|
|
||||||
bool m_VBO;
|
|
||||||
} m_Caps;
|
|
||||||
// build card cap bits
|
|
||||||
void EnumCaps();
|
|
||||||
// per-frame renderer stats
|
|
||||||
Stats m_Stats;
|
|
||||||
};
|
|
||||||
|
|
||||||
// declaration of sole renderer object
|
|
||||||
extern CRenderer g_Renderer;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||||||
//----------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Name: SHCoeffs.h
|
|
||||||
// Last Update: 25/11/03
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@0ad.wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: implementation of 9 component spherical harmonic
|
|
||||||
// lighting
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "SHCoeffs.h"
|
|
||||||
|
|
||||||
CSHCoeffs::CSHCoeffs()
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSHCoeffs::Clear()
|
|
||||||
{
|
|
||||||
for (int i=0;i<9;i++) {
|
|
||||||
_data[i].Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSHCoeffs::AddAmbientLight(const RGBColor& color)
|
|
||||||
{
|
|
||||||
_data[0]+=color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSHCoeffs::AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor)
|
|
||||||
{
|
|
||||||
CVector3D dirToLight(-lightDir.X,-lightDir.Y,-lightDir.Z);
|
|
||||||
|
|
||||||
const float normalisation = PI*16/17;
|
|
||||||
const float c1 = SQR(0.282095f) * normalisation * 1.0f;
|
|
||||||
const float c2 = SQR(0.488603f) * normalisation * (2.0f/3.0f);
|
|
||||||
const float c3 = SQR(1.092548f) * normalisation * (1.0f/4.0f);
|
|
||||||
const float c4 = SQR(0.315392f) * normalisation * (1.0f/4.0f);
|
|
||||||
const float c5 = SQR(0.546274f) * normalisation * (1.0f/4.0f);
|
|
||||||
|
|
||||||
_data[0]+=lightColor*c1;
|
|
||||||
_data[1]+=lightColor*c2*dirToLight.X;
|
|
||||||
_data[2]+=lightColor*c2*dirToLight.Y;
|
|
||||||
_data[3]+=lightColor*c2*dirToLight.Z;
|
|
||||||
_data[4]+=lightColor*c3*dirToLight.X*dirToLight.Z;
|
|
||||||
_data[5]+=lightColor*c3*dirToLight.Z*dirToLight.Y;
|
|
||||||
_data[6]+=lightColor*c3*dirToLight.Y*dirToLight.X;
|
|
||||||
_data[7]+=lightColor*c4*(3.0f*SQR(dirToLight.Z)-1.0f);
|
|
||||||
_data[8]+=lightColor*c5*(SQR(dirToLight.X)-SQR(dirToLight.Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color) const
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
float c4=normal.X*normal.Z;
|
|
||||||
float c5=normal.Z*normal.Y;
|
|
||||||
float c6=normal.Y*normal.X;
|
|
||||||
float c7=(3*SQR(normal.Z)-1.0f);
|
|
||||||
float c8=(SQR(normal.X)-SQR(normal.Y));
|
|
||||||
|
|
||||||
for (int i=0;i<3;i++) {
|
|
||||||
color[i]=_data[0][i];
|
|
||||||
color[i]+=_data[1][i]*normal.X;
|
|
||||||
color[i]+=_data[2][i]*normal.Y;
|
|
||||||
color[i]+=_data[3][i]*normal.Z;
|
|
||||||
color[i]+=_data[4][i]*c4;
|
|
||||||
color[i]+=_data[5][i]*c5;
|
|
||||||
color[i]+=_data[6][i]*c6;
|
|
||||||
color[i]+=_data[7][i]*c7;
|
|
||||||
color[i]+=_data[8][i]*c8;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// debug aid: output quantised normal
|
|
||||||
color=RGBColor((normal.X+1)*0.5,(normal.Y+1)*0.5,(normal.Z+1)*0.5);
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
//----------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Name: SHCoeffs.h
|
|
||||||
// Last Update: 25/11/03
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@0ad.wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: implementation of 9 component spherical harmonic
|
|
||||||
// lighting
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __SHCOEFFS_H
|
|
||||||
#define __SHCOEFFS_H
|
|
||||||
|
|
||||||
#include "Color.h"
|
|
||||||
|
|
||||||
class CSHCoeffs
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CSHCoeffs();
|
|
||||||
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
void AddAmbientLight(const RGBColor& color);
|
|
||||||
void AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor);
|
|
||||||
|
|
||||||
void Evaluate(const CVector3D& normal,RGBColor& color) const;
|
|
||||||
|
|
||||||
const RGBColor* GetCoefficients() const { return _data; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
RGBColor _data[9];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,105 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: SkeletonAnim.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "SkeletonAnim.h"
|
|
||||||
#include "FilePacker.h"
|
|
||||||
#include "FileUnpacker.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CSkeletonAnim constructor
|
|
||||||
CSkeletonAnim::CSkeletonAnim() : m_Keys(0), m_NumKeys(0), m_NumFrames(0), m_FrameTime(0)
|
|
||||||
{
|
|
||||||
m_Name[0]='\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CSkeletonAnim destructor
|
|
||||||
CSkeletonAnim::~CSkeletonAnim()
|
|
||||||
{
|
|
||||||
delete[] m_Keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// BuildBoneMatrices: build matrices for all bones at the given time (in MS) in this
|
|
||||||
// animation
|
|
||||||
void CSkeletonAnim::BuildBoneMatrices(float time,CMatrix3D* matrices) const
|
|
||||||
{
|
|
||||||
float fstartframe=time/m_FrameTime;
|
|
||||||
u32 startframe=u32(time/m_FrameTime);
|
|
||||||
float deltatime=fstartframe-startframe;
|
|
||||||
|
|
||||||
startframe%=m_NumFrames;
|
|
||||||
|
|
||||||
u32 endframe=startframe+1;
|
|
||||||
endframe%=m_NumFrames;
|
|
||||||
|
|
||||||
u32 i;
|
|
||||||
for (i=0;i<m_NumKeys;i++) {
|
|
||||||
const Key& startkey=GetKey(startframe,i);
|
|
||||||
const Key& endkey=GetKey(endframe,i);
|
|
||||||
|
|
||||||
CVector3D trans=startkey.m_Translation*(1-deltatime)+endkey.m_Translation*deltatime;
|
|
||||||
CQuaternion rot;
|
|
||||||
rot.Slerp(startkey.m_Rotation,endkey.m_Rotation,deltatime);
|
|
||||||
|
|
||||||
matrices[i].SetIdentity();
|
|
||||||
matrices[i].Rotate(rot);
|
|
||||||
matrices[i].Translate(trans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Load: try to load the anim from given file; return a new anim if successful
|
|
||||||
CSkeletonAnim* CSkeletonAnim::Load(const char* filename)
|
|
||||||
{
|
|
||||||
CFileUnpacker unpacker;
|
|
||||||
unpacker.Read(filename,"PSSA");
|
|
||||||
|
|
||||||
// check version
|
|
||||||
if (unpacker.GetVersion()<FILE_READ_VERSION) {
|
|
||||||
throw CFileUnpacker::CFileVersionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack the data
|
|
||||||
CSkeletonAnim* anim=new CSkeletonAnim;
|
|
||||||
try {
|
|
||||||
CStr str;
|
|
||||||
unpacker.UnpackString(str);
|
|
||||||
strcpy(anim->m_Name,(const char*) str);
|
|
||||||
|
|
||||||
unpacker.UnpackRaw(&anim->m_FrameTime,sizeof(anim->m_FrameTime));
|
|
||||||
unpacker.UnpackRaw(&anim->m_NumKeys,sizeof(anim->m_NumKeys));
|
|
||||||
unpacker.UnpackRaw(&anim->m_NumFrames,sizeof(anim->m_NumFrames));
|
|
||||||
anim->m_Keys=new Key[anim->m_NumKeys*anim->m_NumFrames];
|
|
||||||
unpacker.UnpackRaw(anim->m_Keys,anim->m_NumKeys*anim->m_NumFrames*sizeof(Key));
|
|
||||||
} catch (...) {
|
|
||||||
delete anim;
|
|
||||||
throw CFileUnpacker::CFileEOFError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return anim;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Save: try to save anim to file
|
|
||||||
void CSkeletonAnim::Save(const char* filename,const CSkeletonAnim* anim)
|
|
||||||
{
|
|
||||||
CFilePacker packer;
|
|
||||||
|
|
||||||
// pack up all the data
|
|
||||||
packer.PackString(CStr(anim->m_Name));
|
|
||||||
packer.PackRaw(&anim->m_FrameTime,sizeof(anim->m_FrameTime));
|
|
||||||
packer.PackRaw(&anim->m_NumKeys,sizeof(anim->m_NumKeys));
|
|
||||||
packer.PackRaw(&anim->m_NumFrames,sizeof(anim->m_NumFrames));
|
|
||||||
packer.PackRaw(anim->m_Keys,anim->m_NumKeys*anim->m_NumFrames*sizeof(Key));
|
|
||||||
|
|
||||||
// now write it
|
|
||||||
packer.Write(filename,FILE_VERSION,"PSSA");
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: SkeletonAnim.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef _SKELETONANIM_H
|
|
||||||
#define _SKELETONANIM_H
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Quaternion.h"
|
|
||||||
|
|
||||||
#ifndef MAX_NAME_LENGTH
|
|
||||||
#define MAX_NAME_LENGTH 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CBoneState: structure describing state of a bone at some point
|
|
||||||
class CBoneState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// translation of bone relative to root
|
|
||||||
CVector3D m_Translation;
|
|
||||||
// rotation of bone relative to root
|
|
||||||
CQuaternion m_Rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CSkeletonAnim: description of an animation that plays upon a skeleton
|
|
||||||
class CSkeletonAnim
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// current file version given to saved animations
|
|
||||||
enum { FILE_VERSION = 1 };
|
|
||||||
// supported file read version - files with a version less than this will be rejected
|
|
||||||
enum { FILE_READ_VERSION = 1 };
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Key: description of a single key in a skeleton animation
|
|
||||||
typedef CBoneState Key;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// CSkeletonAnim constructor + destructor
|
|
||||||
CSkeletonAnim();
|
|
||||||
~CSkeletonAnim();
|
|
||||||
|
|
||||||
// return the number of keys in this animation
|
|
||||||
u32 GetNumKeys() const { return m_NumKeys; }
|
|
||||||
|
|
||||||
// accessors: get a key for given bone at given time
|
|
||||||
Key& GetKey(u32 frame,u32 bone) { return m_Keys[frame*m_NumKeys+bone]; }
|
|
||||||
const Key& GetKey(u32 frame,u32 bone) const { return m_Keys[frame*m_NumKeys+bone]; }
|
|
||||||
|
|
||||||
// get duration of this anim, in ms
|
|
||||||
float GetDuration() const { return m_NumFrames*m_FrameTime; }
|
|
||||||
|
|
||||||
// build matrices for all bones at the given time (in MS) in this animation
|
|
||||||
void BuildBoneMatrices(float time,CMatrix3D* matrices) const;
|
|
||||||
|
|
||||||
// anim I/O functions
|
|
||||||
static CSkeletonAnim* Load(const char* filename);
|
|
||||||
static void Save(const char* filename,const CSkeletonAnim* anim);
|
|
||||||
|
|
||||||
public:
|
|
||||||
// name of the animation
|
|
||||||
char m_Name[MAX_NAME_LENGTH];
|
|
||||||
// frame time - time between successive frames, in ms
|
|
||||||
float m_FrameTime;
|
|
||||||
// number of keys in each frame - should match number of bones in the skeleton
|
|
||||||
u32 m_NumKeys;
|
|
||||||
// number of frames in the animation
|
|
||||||
u32 m_NumFrames;
|
|
||||||
// animation data - m_NumKeys*m_NumFrames total keys
|
|
||||||
Key* m_Keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,214 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: Sprite.cpp
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: Billboarding sprite class - always faces the camera. It
|
|
||||||
| does this by getting the current model view matrix state.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: The functions speak for themselves. Instantiate, then be
|
|
||||||
| sure to pass a loaded (using tex_load()) texture before
|
|
||||||
| calling Render().
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#include "Sprite.h"
|
|
||||||
#include "ogl.h"
|
|
||||||
#include "res/tex.h"
|
|
||||||
|
|
||||||
CSprite::CSprite() :
|
|
||||||
m_texture(NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
// default scale 1:1
|
|
||||||
m_scale.X = m_scale.Y = m_scale.Z = 1.0f;
|
|
||||||
|
|
||||||
// default position (0.0f, 0.0f, 0.0f)
|
|
||||||
m_translation.X = m_translation.Y = m_translation.Z = 0.0f;
|
|
||||||
|
|
||||||
// default size 1.0 x 1.0
|
|
||||||
SetSize(1.0f, 1.0f);
|
|
||||||
|
|
||||||
// default colour, white
|
|
||||||
m_colour[0] = m_colour[1] = m_colour[2] = m_colour[3] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSprite::~CSprite()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::Render()
|
|
||||||
{
|
|
||||||
BeginBillboard();
|
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
glTranslatef(m_translation.X, m_translation.Y, m_translation.Z);
|
|
||||||
glScalef(m_scale.X, m_scale.Y, m_scale.Z);
|
|
||||||
|
|
||||||
tex_bind(m_texture->GetHandle());
|
|
||||||
|
|
||||||
glColor4fv(m_colour);
|
|
||||||
|
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
|
||||||
// bottom left
|
|
||||||
glTexCoord2f(0.0f, 0.0f);
|
|
||||||
glVertex3fv((GLfloat *) &m_coords[0]);
|
|
||||||
|
|
||||||
// top left
|
|
||||||
glTexCoord2f(0.0f, 1.0f);
|
|
||||||
glVertex3fv((GLfloat *) &m_coords[1]);
|
|
||||||
|
|
||||||
// bottom right
|
|
||||||
glTexCoord2f(1.0f, 0.0f);
|
|
||||||
glVertex3fv((GLfloat *) &m_coords[2]);
|
|
||||||
|
|
||||||
// top left
|
|
||||||
glTexCoord2f(1.0f, 1.0f);
|
|
||||||
glVertex3fv((GLfloat *) &m_coords[3]);
|
|
||||||
glEnd();
|
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
EndBillboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSprite::SetTexture(CTexture *texture)
|
|
||||||
{
|
|
||||||
if (texture == NULL) return -1;
|
|
||||||
|
|
||||||
m_texture = texture;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetSize(float width, float height)
|
|
||||||
{
|
|
||||||
m_width = width;
|
|
||||||
m_height = height;
|
|
||||||
|
|
||||||
float xOffset = m_width / 2;
|
|
||||||
float yOffset = m_height / 2;
|
|
||||||
|
|
||||||
// bottom left
|
|
||||||
m_coords[0].X = - (xOffset);
|
|
||||||
m_coords[0].Y = - (yOffset);
|
|
||||||
m_coords[0].Z = 0.0f;
|
|
||||||
|
|
||||||
// top left
|
|
||||||
m_coords[1].X = - (xOffset);
|
|
||||||
m_coords[1].Y = yOffset;
|
|
||||||
m_coords[1].Z = 0.0f;
|
|
||||||
|
|
||||||
// bottom right
|
|
||||||
m_coords[2].X = xOffset;
|
|
||||||
m_coords[2].Y = - (yOffset);
|
|
||||||
m_coords[2].Z = 0.0f;
|
|
||||||
|
|
||||||
// top right
|
|
||||||
m_coords[3].X = xOffset;
|
|
||||||
m_coords[3].Y = yOffset;
|
|
||||||
m_coords[3].Z = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float CSprite::GetWidth()
|
|
||||||
{
|
|
||||||
return m_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetWidth(float width)
|
|
||||||
{
|
|
||||||
SetSize(width, m_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
float CSprite::GetHeight()
|
|
||||||
{
|
|
||||||
return m_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetHeight(float height)
|
|
||||||
{
|
|
||||||
SetSize(m_width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector3D CSprite::GetTranslation()
|
|
||||||
{
|
|
||||||
return m_translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetTranslation(CVector3D trans)
|
|
||||||
{
|
|
||||||
m_translation = trans;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetTranslation(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_translation.X = x;
|
|
||||||
m_translation.Y = y;
|
|
||||||
m_translation.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector3D CSprite::GetScale()
|
|
||||||
{
|
|
||||||
return m_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetScale(CVector3D scale)
|
|
||||||
{
|
|
||||||
m_scale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetScale(float x, float y, float z)
|
|
||||||
{
|
|
||||||
m_scale.X = x;
|
|
||||||
m_scale.Y = y;
|
|
||||||
m_scale.Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::SetColour(float * colour)
|
|
||||||
{
|
|
||||||
m_colour[0] = colour[0];
|
|
||||||
m_colour[1] = colour[1];
|
|
||||||
m_colour[2] = colour[2];
|
|
||||||
m_colour[3] = colour[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// should be called before any other gl calls
|
|
||||||
void CSprite::BeginBillboard()
|
|
||||||
{
|
|
||||||
float newMatrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.0f, 1.0f };
|
|
||||||
float currentMatrix[16];
|
|
||||||
|
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, currentMatrix);
|
|
||||||
newMatrix[0] = currentMatrix[0];
|
|
||||||
newMatrix[1] = currentMatrix[4];
|
|
||||||
newMatrix[2] = currentMatrix[8];
|
|
||||||
newMatrix[4] = currentMatrix[1];
|
|
||||||
newMatrix[5] = currentMatrix[5];
|
|
||||||
newMatrix[6] = currentMatrix[9];
|
|
||||||
newMatrix[8] = currentMatrix[2];
|
|
||||||
newMatrix[9] = currentMatrix[6];
|
|
||||||
newMatrix[10] = currentMatrix[10];
|
|
||||||
|
|
||||||
glPushMatrix();
|
|
||||||
glMultMatrixf(newMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSprite::EndBillboard()
|
|
||||||
{
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
/*==================================================================
|
|
||||||
|
|
|
||||||
| Name: Sprite.h
|
|
||||||
|
|
|
||||||
|===================================================================
|
|
||||||
|
|
|
||||||
| Author: Ben Vinegar
|
|
||||||
| Contact: benvinegar () hotmail ! com
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Last Modified: 03/08/04
|
|
||||||
|
|
|
||||||
| Overview: Billboarding sprite class - always faces the camera. It
|
|
||||||
| does this by getting the current model view matrix state.
|
|
||||||
|
|
|
||||||
|
|
|
||||||
| Usage: The functions speak for themselves. Instantiate, then be
|
|
||||||
| sure to pass a loaded (using tex_load()) texture before
|
|
||||||
| calling Render().
|
|
||||||
|
|
|
||||||
| To do: TBA
|
|
||||||
|
|
|
||||||
| More Information: TBA
|
|
||||||
|
|
|
||||||
==================================================================*/
|
|
||||||
|
|
||||||
#ifndef SPRITE_H
|
|
||||||
#define SPRITE_H
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Includes / Compiler directives
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
#include "Vector3D.h"
|
|
||||||
#include "Texture.h"
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// Declarations
|
|
||||||
//--------------------------------------------------------
|
|
||||||
|
|
||||||
class CSprite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CSprite();
|
|
||||||
~CSprite();
|
|
||||||
|
|
||||||
void Render();
|
|
||||||
|
|
||||||
int SetTexture(CTexture *texture);
|
|
||||||
|
|
||||||
void SetSize(float width, float height);
|
|
||||||
|
|
||||||
float GetWidth();
|
|
||||||
void SetWidth(float width);
|
|
||||||
|
|
||||||
float GetHeight();
|
|
||||||
void SetHeight(float height);
|
|
||||||
|
|
||||||
CVector3D GetTranslation();
|
|
||||||
void SetTranslation(CVector3D pos);
|
|
||||||
void SetTranslation(float x, float y, float z);
|
|
||||||
|
|
||||||
CVector3D GetScale();
|
|
||||||
void SetScale(CVector3D scale);
|
|
||||||
void SetScale(float x, float y, float z);
|
|
||||||
|
|
||||||
void SetColour(float * colour);
|
|
||||||
void SetColour(float r, float g, float b, float a = 1.0f);
|
|
||||||
private:
|
|
||||||
void BeginBillboard();
|
|
||||||
void EndBillboard();
|
|
||||||
|
|
||||||
CTexture *m_texture;
|
|
||||||
|
|
||||||
CVector3D m_coords[4];
|
|
||||||
|
|
||||||
float m_width;
|
|
||||||
float m_height;
|
|
||||||
|
|
||||||
CVector3D m_translation;
|
|
||||||
CVector3D m_scale;
|
|
||||||
|
|
||||||
float m_colour[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SPRITE_H
|
|
@ -1,292 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Terrain.cpp
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "res/tex.h"
|
|
||||||
#include "res/mem.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "Terrain.h"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CTerrain constructor
|
|
||||||
CTerrain::CTerrain() : m_Heightmap(0), m_Patches(0), m_MapSize(0), m_MapSizePatches(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CTerrain constructor
|
|
||||||
CTerrain::~CTerrain()
|
|
||||||
{
|
|
||||||
ReleaseData();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ReleaseData: delete any data allocated by this terrain
|
|
||||||
void CTerrain::ReleaseData()
|
|
||||||
{
|
|
||||||
delete[] m_Heightmap;
|
|
||||||
delete[] m_Patches;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Initialise: initialise this terrain to the given size (in patches per side);
|
|
||||||
// using given heightmap to setup elevation data
|
|
||||||
bool CTerrain::Initialize(u32 size,const u16* data)
|
|
||||||
{
|
|
||||||
// clean up any previous terrain
|
|
||||||
ReleaseData();
|
|
||||||
|
|
||||||
// store terrain size
|
|
||||||
m_MapSize=(size*PATCH_SIZE)+1;
|
|
||||||
m_MapSizePatches=size;
|
|
||||||
|
|
||||||
// allocate data for new terrain
|
|
||||||
m_Heightmap=new u16[m_MapSize*m_MapSize];
|
|
||||||
m_Patches=new CPatch[m_MapSizePatches*m_MapSizePatches];
|
|
||||||
|
|
||||||
// given a heightmap?
|
|
||||||
if (data) {
|
|
||||||
// yes; keep a copy of it
|
|
||||||
memcpy(m_Heightmap,data,m_MapSize*m_MapSize*sizeof(u16));
|
|
||||||
} else {
|
|
||||||
// build a flat terrain
|
|
||||||
memset(m_Heightmap,0,m_MapSize*m_MapSize*sizeof(u16));
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup patch parents, indices etc
|
|
||||||
InitialisePatches();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CalcPosition: calculate the world space position of the vertex at (i,j)
|
|
||||||
void CTerrain::CalcPosition(u32 i,u32 j,CVector3D& pos)
|
|
||||||
{
|
|
||||||
u16 height=m_Heightmap[j*m_MapSize + i];
|
|
||||||
pos.X = float(i)*CELL_SIZE;
|
|
||||||
pos.Y = float(height)*HEIGHT_SCALE;
|
|
||||||
pos.Z = float(j)*CELL_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CalcNormal: calculate the world space normal of the vertex at (i,j)
|
|
||||||
void CTerrain::CalcNormal(u32 i,u32 j,CVector3D& normal)
|
|
||||||
{
|
|
||||||
CVector3D left, right, up, down;
|
|
||||||
|
|
||||||
left.Clear();
|
|
||||||
right.Clear();
|
|
||||||
up.Clear();
|
|
||||||
down.Clear();
|
|
||||||
|
|
||||||
// get position of vertex where normal is being evaluated
|
|
||||||
CVector3D basepos;
|
|
||||||
CalcPosition(i,j,basepos);
|
|
||||||
|
|
||||||
CVector3D tmp;
|
|
||||||
if (i>0) {
|
|
||||||
CalcPosition(i-1,j,tmp);
|
|
||||||
left=tmp-basepos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i<m_MapSize-1) {
|
|
||||||
CalcPosition(i+1,j,tmp);
|
|
||||||
right=tmp-basepos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j>0) {
|
|
||||||
CalcPosition(i,j-1,tmp);
|
|
||||||
up=tmp-basepos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j<m_MapSize-1) {
|
|
||||||
CalcPosition(i,j+1,tmp);
|
|
||||||
down=tmp-basepos;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector3D n0 = up.Cross(left);
|
|
||||||
CVector3D n1 = left.Cross(down);
|
|
||||||
CVector3D n2 = down.Cross(right);
|
|
||||||
CVector3D n3 = right.Cross(up);
|
|
||||||
|
|
||||||
normal = n0 + n1 + n2 + n3;
|
|
||||||
float nlen=normal.GetLength();
|
|
||||||
if (nlen>0.00001f) normal*=1.0f/nlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
|
|
||||||
// out of bounds
|
|
||||||
CPatch* CTerrain::GetPatch(int32 x,int32 z)
|
|
||||||
{
|
|
||||||
if (x<0 || x>=int32(m_MapSizePatches)) return 0;
|
|
||||||
if (z<0 || z>=int32(m_MapSizePatches)) return 0;
|
|
||||||
return &m_Patches[(z*m_MapSizePatches)+x];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
|
|
||||||
// of bounds
|
|
||||||
CMiniPatch* CTerrain::GetTile(int32 x,int32 z)
|
|
||||||
{
|
|
||||||
if (x<0 || x>=int32(m_MapSize)-1) return 0;
|
|
||||||
if (z<0 || z>=int32(m_MapSize)-1) return 0;
|
|
||||||
|
|
||||||
CPatch* patch=GetPatch(x/16,z/16);
|
|
||||||
return &patch->m_MiniPatches[z%16][x%16];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Resize: resize this terrain to the given size (in patches per side)
|
|
||||||
void CTerrain::Resize(u32 size)
|
|
||||||
{
|
|
||||||
if (size==m_MapSizePatches) {
|
|
||||||
// inexplicable request to resize terrain to the same size .. ignore it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_Heightmap) {
|
|
||||||
// not yet created a terrain; build a default terrain of the given size now
|
|
||||||
Initialize(size,0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate data for new terrain
|
|
||||||
u32 newMapSize=(size*PATCH_SIZE)+1;
|
|
||||||
u16* newHeightmap=new u16[newMapSize*newMapSize];
|
|
||||||
CPatch* newPatches=new CPatch[size*size];
|
|
||||||
|
|
||||||
if (size>m_MapSizePatches) {
|
|
||||||
// new map is bigger than old one - zero the heightmap so we don't get uninitialised
|
|
||||||
// height data along the expanded edges
|
|
||||||
memset(newHeightmap,0,newMapSize*newMapSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now copy over rows of data
|
|
||||||
u32 j;
|
|
||||||
u16* src=m_Heightmap;
|
|
||||||
u16* dst=newHeightmap;
|
|
||||||
u32 copysize=newMapSize>m_MapSize ? m_MapSize : newMapSize;
|
|
||||||
for (j=0;j<copysize;j++) {
|
|
||||||
memcpy(dst,src,copysize*sizeof(u16));
|
|
||||||
dst+=copysize;
|
|
||||||
src+=m_MapSize;
|
|
||||||
if (newMapSize>m_MapSize) {
|
|
||||||
// entend the last height to the end of the row
|
|
||||||
for (u32 i=0;i<newMapSize-m_MapSize;i++) {
|
|
||||||
*dst++=*(src-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (newMapSize>m_MapSize) {
|
|
||||||
// copy over heights of the last row to any remaining rows
|
|
||||||
src=newHeightmap+((m_MapSize-1)*newMapSize);
|
|
||||||
dst=src+newMapSize;
|
|
||||||
for (u32 i=0;i<newMapSize-m_MapSize;i++) {
|
|
||||||
memcpy(dst,src,newMapSize*sizeof(u16));
|
|
||||||
dst+=newMapSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now build new patches
|
|
||||||
for (j=0;j<size;j++) {
|
|
||||||
for (u32 i=0;i<size;i++) {
|
|
||||||
// copy over texture data from existing tiles, if possible
|
|
||||||
if (i<m_MapSizePatches && j<m_MapSizePatches) {
|
|
||||||
memcpy(newPatches[j*size+i].m_MiniPatches,m_Patches[j*m_MapSizePatches+i].m_MiniPatches,sizeof(CMiniPatch)*16*16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j<m_MapSizePatches && size>m_MapSizePatches) {
|
|
||||||
// copy over the last tile from each column
|
|
||||||
for (u32 n=0;n<size-m_MapSizePatches;n++) {
|
|
||||||
for (int m=0;m<16;m++) {
|
|
||||||
CMiniPatch& src=m_Patches[j*m_MapSizePatches+m_MapSizePatches-1].m_MiniPatches[m][15];
|
|
||||||
for (int k=0;k<16;k++) {
|
|
||||||
CMiniPatch& dst=newPatches[j*size+m_MapSizePatches+n].m_MiniPatches[m][k];
|
|
||||||
dst.Tex1=src.Tex1;
|
|
||||||
dst.Tex1Priority=src.Tex1Priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size>m_MapSizePatches) {
|
|
||||||
// copy over the last tile from each column
|
|
||||||
CPatch* srcpatch=&newPatches[(m_MapSizePatches-1)*size];
|
|
||||||
CPatch* dstpatch=srcpatch+size;
|
|
||||||
for (u32 p=0;p<size-m_MapSizePatches;p++) {
|
|
||||||
for (u32 n=0;n<size;n++) {
|
|
||||||
for (int m=0;m<16;m++) {
|
|
||||||
for (int k=0;k<16;k++) {
|
|
||||||
CMiniPatch& src=srcpatch->m_MiniPatches[15][k];
|
|
||||||
CMiniPatch& dst=dstpatch->m_MiniPatches[m][k];
|
|
||||||
dst.Tex1=src.Tex1;
|
|
||||||
dst.Tex1Priority=src.Tex1Priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
srcpatch++;
|
|
||||||
dstpatch++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// release all the original data
|
|
||||||
ReleaseData();
|
|
||||||
|
|
||||||
// store new data
|
|
||||||
m_Heightmap=newHeightmap;
|
|
||||||
m_Patches=newPatches;
|
|
||||||
m_MapSize=newMapSize;
|
|
||||||
m_MapSizePatches=size;
|
|
||||||
|
|
||||||
// initialise all the new patches
|
|
||||||
InitialisePatches();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// InitialisePatches: initialise patch data
|
|
||||||
void CTerrain::InitialisePatches()
|
|
||||||
{
|
|
||||||
for (u32 j=0;j<m_MapSizePatches;j++) {
|
|
||||||
for (u32 i=0;i<m_MapSizePatches;i++) {
|
|
||||||
CPatch* patch=GetPatch(i,j);
|
|
||||||
patch->Initialize(this,i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// SetHeightMap: set up a new heightmap from 16-bit source data;
|
|
||||||
// assumes heightmap matches current terrain size
|
|
||||||
void CTerrain::SetHeightMap(u16* heightmap)
|
|
||||||
{
|
|
||||||
// keep a copy of the given heightmap
|
|
||||||
memcpy(m_Heightmap,heightmap,m_MapSize*m_MapSize*sizeof(u16));
|
|
||||||
|
|
||||||
// recalculate patch bounds, invalidate vertices
|
|
||||||
for (u32 j=0;j<m_MapSizePatches;j++) {
|
|
||||||
for (u32 i=0;i<m_MapSizePatches;i++) {
|
|
||||||
CPatch* patch=GetPatch(i,j);
|
|
||||||
patch->CalcBounds();
|
|
||||||
patch->SetDirty(RENDERDATA_UPDATE_VERTICES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Name: Terrain.h
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@wildfiregames.com
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _TERRAIN_H
|
|
||||||
#define _TERRAIN_H
|
|
||||||
|
|
||||||
#include "Patch.h"
|
|
||||||
#include "Vector3D.h"
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Terrain Constants:
|
|
||||||
//
|
|
||||||
// PATCH_SIZE: number of tiles in each patch
|
|
||||||
const int PATCH_SIZE = 16;
|
|
||||||
// CELL_SIZE: size of each tile in x and z
|
|
||||||
const int CELL_SIZE = 4;
|
|
||||||
// HEIGHT_SCALE: vertical scale of terrain - terrain has a coordinate range of
|
|
||||||
// 0 to 65536*HEIGHT_SCALE
|
|
||||||
const float HEIGHT_SCALE = 0.35f/256.0f;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CTerrain: main terrain class; contains the heightmap describing elevation
|
|
||||||
// data, and the smaller subpatches that form the terrain
|
|
||||||
class CTerrain
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CTerrain();
|
|
||||||
~CTerrain();
|
|
||||||
|
|
||||||
bool Initialize(u32 size,const u16* ptr);
|
|
||||||
|
|
||||||
// return number of vertices along edge of the terrain
|
|
||||||
u32 GetVerticesPerSide() { return m_MapSize; }
|
|
||||||
// return number of patches along edge of the terrain
|
|
||||||
u32 GetPatchesPerSide() { return m_MapSizePatches; }
|
|
||||||
|
|
||||||
// resize this terrain such that each side has given number of patches
|
|
||||||
void Resize(u32 size);
|
|
||||||
|
|
||||||
// set up a new heightmap from 16 bit data; assumes heightmap matches current terrain size
|
|
||||||
void SetHeightMap(u16* heightmap);
|
|
||||||
// return a pointer to the heightmap
|
|
||||||
u16* GetHeightMap() const { return m_Heightmap; }
|
|
||||||
|
|
||||||
// get patch at given coordinates, expressed in patch-space; return 0 if
|
|
||||||
// coordinates represent patch off the edge of the map
|
|
||||||
CPatch* GetPatch(int32 x,int32 z);
|
|
||||||
// get tile at given coordinates, expressed in tile-space; return 0 if
|
|
||||||
// coordinates represent tile off the edge of the map
|
|
||||||
CMiniPatch* GetTile(int32 x,int32 z);
|
|
||||||
|
|
||||||
// calculate the position of a given vertex
|
|
||||||
void CalcPosition(u32 i,u32 j,CVector3D& pos);
|
|
||||||
// calculate the normal at a given vertex
|
|
||||||
void CalcNormal(u32 i,u32 j,CVector3D& normal);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// delete any data allocated by this terrain
|
|
||||||
void ReleaseData();
|
|
||||||
// setup patch pointers etc
|
|
||||||
void InitialisePatches();
|
|
||||||
|
|
||||||
// size of this map in each direction, in vertices; ie. total tiles = sqr(m_MapSize-1)
|
|
||||||
u32 m_MapSize;
|
|
||||||
// size of this map in each direction, in patches; total patches = sqr(m_MapSizePatches)
|
|
||||||
u32 m_MapSizePatches;
|
|
||||||
// the patches comprising this terrain
|
|
||||||
CPatch* m_Patches;
|
|
||||||
// 16-bit heightmap data
|
|
||||||
u16* m_Heightmap;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CTerrain g_Terrain;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||||||
//-----------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Name: Texture.h
|
|
||||||
// Last Update: 25/11/03
|
|
||||||
// Author: Rich Cross
|
|
||||||
// Contact: rich@0ad.wildfiregames.com
|
|
||||||
//
|
|
||||||
// Description: Basic texture class
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef _TEXTURE_H
|
|
||||||
#define _TEXTURE_H
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
|
|
||||||
class CTexture
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CTexture() : m_Handle(0) {}
|
|
||||||
CTexture(const char* name) : m_Name(name), m_Handle(0) {}
|
|
||||||
|
|
||||||
void SetName(const char* name) { m_Name=name; }
|
|
||||||
const char* GetName() const { return (const char*) m_Name; }
|
|
||||||
|
|
||||||
Handle GetHandle() const { return m_Handle; }
|
|
||||||
void SetHandle(Handle handle) { m_Handle=handle; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
CStr m_Name;
|
|
||||||
Handle m_Handle;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef _TEXTUREENTRY_H
|
|
||||||
#define _TEXTUREENTRY_H
|
|
||||||
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
|
|
||||||
class CTextureEntry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CTextureEntry() : m_Bitmap(0), m_Handle(0), m_BaseColor(0), m_Type(0) {}
|
|
||||||
|
|
||||||
// filename
|
|
||||||
CStr m_Name;
|
|
||||||
// UI bitmap object
|
|
||||||
void* m_Bitmap;
|
|
||||||
// handle to GL texture data
|
|
||||||
Handle m_Handle;
|
|
||||||
// BGRA color of topmost mipmap level, for coloring minimap
|
|
||||||
unsigned int m_BaseColor;
|
|
||||||
// "type" of texture - index into TextureManager texturetypes array
|
|
||||||
int m_Type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,201 +0,0 @@
|
|||||||
|
|
||||||
#include "TextureManager.h"
|
|
||||||
#include "lib.h"
|
|
||||||
#include "ogl.h"
|
|
||||||
#include "res/tex.h"
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
const char* SupportedTextureFormats[] = { "png", "dds", "tga", "bmp" };
|
|
||||||
|
|
||||||
|
|
||||||
CTextureManager g_TexMan;
|
|
||||||
|
|
||||||
|
|
||||||
CTextureManager::CTextureManager()
|
|
||||||
{
|
|
||||||
m_TerrainTextures.reserve(32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextureManager::AddTextureType(const char* name)
|
|
||||||
{
|
|
||||||
m_TerrainTextures.resize(m_TerrainTextures.size()+1);
|
|
||||||
STextureType& ttype=m_TerrainTextures.back();
|
|
||||||
ttype.m_Name=name;
|
|
||||||
ttype.m_Index=(int)(m_TerrainTextures.size()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTextureEntry* CTextureManager::FindTexture(const char* filename)
|
|
||||||
{
|
|
||||||
// check if file already loaded
|
|
||||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
|
||||||
STextureType& ttype=m_TerrainTextures[k];
|
|
||||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
|
||||||
if (strcmp((const char*) ttype.m_Textures[i]->m_Name,filename)==0) {
|
|
||||||
return ttype.m_Textures[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTextureEntry* CTextureManager::FindTexture(Handle handle)
|
|
||||||
{
|
|
||||||
for (uint k=0;k<m_TerrainTextures.size();k++) {
|
|
||||||
STextureType& ttype=m_TerrainTextures[k];
|
|
||||||
for (uint i=0;i<ttype.m_Textures.size();i++) {
|
|
||||||
if (handle==ttype.m_Textures[i]->m_Handle) {
|
|
||||||
return ttype.m_Textures[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTextureEntry* CTextureManager::AddTexture(const char* filename,int type)
|
|
||||||
{
|
|
||||||
assert((uint)type<m_TerrainTextures.size());
|
|
||||||
|
|
||||||
CStr pathname("art/textures/terrain/types/");
|
|
||||||
pathname+=m_TerrainTextures[type].m_Name;
|
|
||||||
pathname+='/';
|
|
||||||
pathname+=filename;
|
|
||||||
|
|
||||||
Handle h=tex_load((const char*) pathname);
|
|
||||||
if (!h) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
int tw;
|
|
||||||
int th;
|
|
||||||
|
|
||||||
tex_info(h, &tw, &th, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
tw &= (tw-1);
|
|
||||||
th &= (th-1);
|
|
||||||
if (tw || th) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create new texture entry
|
|
||||||
CTextureEntry* texentry=new CTextureEntry;
|
|
||||||
texentry->m_Name=filename;
|
|
||||||
texentry->m_Handle=h;
|
|
||||||
texentry->m_Type=type;
|
|
||||||
|
|
||||||
// upload texture for future GL use
|
|
||||||
tex_upload(h,GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
|
|
||||||
// setup texture to repeat
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
||||||
|
|
||||||
// get root color for coloring minimap by querying root level of the texture
|
|
||||||
// (this should decompress any compressed textures for us),
|
|
||||||
// then scaling it down to a 1x1 size
|
|
||||||
// - an alternative approach of just grabbing the top level of the mipmap tree fails
|
|
||||||
// (or gives an incorrect colour) in some cases:
|
|
||||||
// - suspect bug on Radeon cards when SGIS_generate_mipmap is used
|
|
||||||
// - any textures without mipmaps
|
|
||||||
// we'll just take the basic approach here:
|
|
||||||
int width,height;
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
|
|
||||||
|
|
||||||
unsigned char* buf=new unsigned char[width*height*4];
|
|
||||||
glGetTexImage(GL_TEXTURE_2D,0,GL_BGRA_EXT,GL_UNSIGNED_BYTE,buf);
|
|
||||||
gluScaleImage(GL_BGRA_EXT,width,height,GL_UNSIGNED_BYTE,buf,
|
|
||||||
1,1,GL_UNSIGNED_BYTE,&texentry->m_BaseColor);
|
|
||||||
delete[] buf;
|
|
||||||
|
|
||||||
// add entry to list ..
|
|
||||||
m_TerrainTextures[type].m_Textures.push_back(texentry);
|
|
||||||
|
|
||||||
// .. and return it
|
|
||||||
return texentry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextureManager::DeleteTexture(CTextureEntry* entry)
|
|
||||||
{
|
|
||||||
// find entry in list
|
|
||||||
std::vector<CTextureEntry*>& textures=m_TerrainTextures[entry->m_Type].m_Textures;
|
|
||||||
|
|
||||||
typedef std::vector<CTextureEntry*>::iterator Iter;
|
|
||||||
Iter i=std::find(textures.begin(),textures.end(),entry);
|
|
||||||
if (i!=textures.end()) {
|
|
||||||
textures.erase(i);
|
|
||||||
}
|
|
||||||
delete entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextureManager::LoadTerrainTextures(int terraintype,const char* fileext)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
struct _finddata_t file;
|
|
||||||
intptr_t handle;
|
|
||||||
|
|
||||||
// build pathname
|
|
||||||
CStr pathname("mods\\official\\art\\textures\\terrain\\types\\");
|
|
||||||
pathname+=m_TerrainTextures[terraintype].m_Name;
|
|
||||||
pathname+="\\";
|
|
||||||
|
|
||||||
CStr findname(pathname);
|
|
||||||
findname+="*.";
|
|
||||||
findname+=fileext;
|
|
||||||
|
|
||||||
// Find first matching file in directory for this terrain type
|
|
||||||
if ((handle=_findfirst((const char*) findname,&file))!=-1) {
|
|
||||||
|
|
||||||
AddTexture(file.name,terraintype);
|
|
||||||
|
|
||||||
// Find the rest of the matching files
|
|
||||||
while( _findnext(handle,&file)==0) {
|
|
||||||
AddTexture((const char*) file.name,terraintype);
|
|
||||||
}
|
|
||||||
|
|
||||||
_findclose(handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextureManager::BuildTerrainTypes()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
struct _finddata_t file;
|
|
||||||
intptr_t handle;
|
|
||||||
|
|
||||||
// Find first matching directory in terrain\textures
|
|
||||||
if ((handle=_findfirst("mods\\official\\art\\textures\\terrain\\types\\*",&file))!=-1) {
|
|
||||||
|
|
||||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
|
||||||
AddTextureType(file.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the rest of the matching files
|
|
||||||
while( _findnext(handle,&file)==0) {
|
|
||||||
if ((file.attrib & _A_SUBDIR) && file.name[0]!='.') {
|
|
||||||
AddTextureType(file.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_findclose(handle);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTextureManager::LoadTerrainTextures()
|
|
||||||
{
|
|
||||||
// find all the terrain types by directory name
|
|
||||||
BuildTerrainTypes();
|
|
||||||
|
|
||||||
// now iterate through terrain types loading all textures of that type
|
|
||||||
for (uint i=0;i<m_TerrainTextures.size();i++) {
|
|
||||||
for (uint j=0;j<sizeof(SupportedTextureFormats)/sizeof(const char*);j++) {
|
|
||||||
LoadTerrainTextures(i,SupportedTextureFormats[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
#ifndef _TEXTUREMANAGER_H
|
|
||||||
#define _TEXTUREMANAGER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "TextureEntry.h"
|
|
||||||
#include "CStr.h"
|
|
||||||
|
|
||||||
class CTextureManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct STextureType
|
|
||||||
{
|
|
||||||
// name of this texture type (derived from directory name)
|
|
||||||
CStr m_Name;
|
|
||||||
// index in parent array
|
|
||||||
int m_Index;
|
|
||||||
// list of textures of this type (found from the texture directory)
|
|
||||||
std::vector<CTextureEntry*> m_Textures;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
CTextureManager();
|
|
||||||
|
|
||||||
void LoadTerrainTextures();
|
|
||||||
|
|
||||||
|
|
||||||
void AddTextureType(const char* name);
|
|
||||||
|
|
||||||
CTextureEntry* FindTexture(const char* filename);
|
|
||||||
CTextureEntry* FindTexture(Handle handle);
|
|
||||||
CTextureEntry* AddTexture(const char* filename,int type);
|
|
||||||
void DeleteTexture(CTextureEntry* entry);
|
|
||||||
|
|
||||||
std::vector<STextureType> m_TerrainTextures;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void LoadTerrainTextures(int terraintype,const char* fileext);
|
|
||||||
void BuildTerrainTypes();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CTextureManager g_TexMan;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,136 +0,0 @@
|
|||||||
#include <algorithm>
|
|
||||||
#include "Renderer.h"
|
|
||||||
#include "TransparencyRenderer.h"
|
|
||||||
#include "terrain/Model.h"
|
|
||||||
|
|
||||||
|
|
||||||
CTransparencyRenderer g_TransparencyRenderer;
|
|
||||||
|
|
||||||
|
|
||||||
struct SortObjectsByDist {
|
|
||||||
typedef CTransparencyRenderer::SObject SortObj;
|
|
||||||
|
|
||||||
bool operator()(const SortObj& lhs,const SortObj& rhs) {
|
|
||||||
return lhs.m_Dist>rhs.m_Dist? true : false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void CTransparencyRenderer::Render()
|
|
||||||
{
|
|
||||||
// coarsely sort submitted objects in back to front manner
|
|
||||||
std::sort(m_Objects.begin(),m_Objects.end(),SortObjectsByDist());
|
|
||||||
|
|
||||||
// switch on wireframe if we need it
|
|
||||||
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch on client states
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glEnableClientState(GL_COLOR_ARRAY);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
// setup texture environment to modulate diffuse color with texture color
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
|
||||||
|
|
||||||
// just pass through texture's alpha
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
|
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
|
||||||
|
|
||||||
glEnable(GL_ALPHA_TEST);
|
|
||||||
glAlphaFunc(GL_GREATER,0.975f);
|
|
||||||
|
|
||||||
uint i;
|
|
||||||
for (i=0;i<m_Objects.size();++i) {
|
|
||||||
CModel* model=m_Objects[i].m_Model;
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
modeldata->RenderStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0,model->GetTransform(),true);
|
|
||||||
}
|
|
||||||
|
|
||||||
glDepthMask(0);
|
|
||||||
glAlphaFunc(GL_LEQUAL,0.975f);
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
for (i=0;i<m_Objects.size();++i) {
|
|
||||||
CModel* model=m_Objects[i].m_Model;
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
modeldata->RenderStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0,model->GetTransform(),true);
|
|
||||||
}
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glDisable(GL_ALPHA_TEST);
|
|
||||||
glDepthMask(1);
|
|
||||||
|
|
||||||
// switch off client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
glDisableClientState(GL_COLOR_ARRAY);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
|
|
||||||
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
|
|
||||||
// switch wireframe off again
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
} else if (g_Renderer.m_ModelRenderMode==EDGED_FACES) {
|
|
||||||
// edged faces: need to make a second pass over the data:
|
|
||||||
// first switch on wireframe
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
|
||||||
|
|
||||||
// setup some renderstate ..
|
|
||||||
glDepthMask(0);
|
|
||||||
g_Renderer.SetTexture(0,0);
|
|
||||||
glColor4f(1,1,1,0.75f);
|
|
||||||
glLineWidth(1.0f);
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// .. and some client states
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
// render each model
|
|
||||||
for (i=0;i<m_Objects.size();++i) {
|
|
||||||
CModel* model=m_Objects[i].m_Model;
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
modeldata->RenderStreams(STREAM_POS,model->GetTransform(),true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// .. and switch off the client states
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
// .. and restore the renderstates
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glDepthMask(1);
|
|
||||||
|
|
||||||
// restore fill mode, and we're done
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// all transparent objects rendered; release them
|
|
||||||
m_Objects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTransparencyRenderer::Add(CModel* model)
|
|
||||||
{
|
|
||||||
// resize array, get last object in list
|
|
||||||
m_Objects.resize(m_Objects.size()+1);
|
|
||||||
|
|
||||||
SObject& obj=m_Objects.back();
|
|
||||||
obj.m_Model=model;
|
|
||||||
|
|
||||||
// build transform from object to camera space
|
|
||||||
CMatrix3D objToCam,invcam;
|
|
||||||
g_Renderer.m_Camera.m_Orientation.GetInverse(objToCam);
|
|
||||||
objToCam*=model->GetTransform();
|
|
||||||
|
|
||||||
// resort model indices from back to front, according to camera position - and store
|
|
||||||
// the returned sqrd distance to the centre of the nearest triangle
|
|
||||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
|
||||||
obj.m_Dist=modeldata->BackToFrontIndexSort(objToCam);
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
#ifndef __TRANSPARENCYRENDERER_H
|
|
||||||
#define __TRANSPARENCYRENDERER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class CModel;
|
|
||||||
|
|
||||||
class CTransparencyRenderer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct SObject {
|
|
||||||
// the transparent model
|
|
||||||
CModel* m_Model;
|
|
||||||
// sqrd distance from camera to centre of nearest triangle
|
|
||||||
float m_Dist;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// add object to render in deferred transparency pass
|
|
||||||
void Add(CModel* model);
|
|
||||||
// render all deferred objects
|
|
||||||
void Render();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// list of transparent objects to render
|
|
||||||
std::vector<SObject> m_Objects;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CTransparencyRenderer g_TransparencyRenderer;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||||||
#ifndef _UNIT_H
|
|
||||||
#define _UNIT_H
|
|
||||||
|
|
||||||
class CModel;
|
|
||||||
class CObjectEntry;
|
|
||||||
|
|
||||||
class CUnit
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// object from which unit was created
|
|
||||||
CObjectEntry* m_Object;
|
|
||||||
// object model representation
|
|
||||||
CModel* m_Model;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||||||
#include "res/res.h"
|
|
||||||
#include "UnitManager.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
CUnitManager g_UnitMan;
|
|
||||||
|
|
||||||
void CUnitManager::AddUnit(CUnit* unit)
|
|
||||||
{
|
|
||||||
m_Units.push_back(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CUnitManager::RemoveUnit(CUnit* unit)
|
|
||||||
{
|
|
||||||
// find entry in list
|
|
||||||
typedef std::vector<CUnit*>::iterator Iter;
|
|
||||||
Iter i=std::find(m_Units.begin(),m_Units.end(),unit);
|
|
||||||
if (i!=m_Units.end()) {
|
|
||||||
m_Units.erase(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CUnitManager::DeleteAll()
|
|
||||||
{
|
|
||||||
for (uint i=0;i<m_Units.size();i++) {
|
|
||||||
delete m_Units[i];
|
|
||||||
}
|
|
||||||
m_Units.clear();
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef _UNITMANAGER_H
|
|
||||||
#define _UNITMANAGER_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "Unit.h"
|
|
||||||
|
|
||||||
class CUnitManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CUnitManager() {}
|
|
||||||
|
|
||||||
void AddUnit(CUnit* unit);
|
|
||||||
void RemoveUnit(CUnit* unit);
|
|
||||||
|
|
||||||
void DeleteAll();
|
|
||||||
|
|
||||||
const std::vector<CUnit*>& GetUnits() const { return m_Units; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<CUnit*> m_Units;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern CUnitManager g_UnitMan;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,158 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Vector3D.Cpp
|
|
||||||
// Last Update: 28/1/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: Provides an interface for a vector in R3 and
|
|
||||||
// allows vector and scalar operations on it
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#include "Vector3D.h"
|
|
||||||
|
|
||||||
CVector3D::CVector3D (float x, float y, float z)
|
|
||||||
{
|
|
||||||
X = x;
|
|
||||||
Y = y;
|
|
||||||
Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CVector3D::operator ! () const
|
|
||||||
{
|
|
||||||
if (X != 0.0f ||
|
|
||||||
Y != 0.0f ||
|
|
||||||
Z != 0.0f)
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//vector addition
|
|
||||||
CVector3D CVector3D::operator + (const CVector3D &vector) const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = X + vector.X;
|
|
||||||
Temp.Y = Y + vector.Y;
|
|
||||||
Temp.Z = Z + vector.Z;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//vector addition/assignment
|
|
||||||
CVector3D &CVector3D::operator += (const CVector3D &vector)
|
|
||||||
{
|
|
||||||
X += vector.X;
|
|
||||||
Y += vector.Y;
|
|
||||||
Z += vector.Z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//vector subtraction
|
|
||||||
CVector3D CVector3D::operator - (const CVector3D &vector) const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = X - vector.X;
|
|
||||||
Temp.Y = Y - vector.Y;
|
|
||||||
Temp.Z = Z - vector.Z;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//vector negation
|
|
||||||
CVector3D CVector3D::operator-() const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = -X;
|
|
||||||
Temp.Y = -Y;
|
|
||||||
Temp.Z = -Z;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
//vector subtrcation/assignment
|
|
||||||
CVector3D &CVector3D::operator -= (const CVector3D &vector)
|
|
||||||
{
|
|
||||||
X -= vector.X;
|
|
||||||
Y -= vector.Y;
|
|
||||||
Z -= vector.Z;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//scalar multiplication
|
|
||||||
CVector3D CVector3D::operator * (float value) const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = X * value;
|
|
||||||
Temp.Y = Y * value;
|
|
||||||
Temp.Z = Z * value;
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
//scalar multiplication/assignment
|
|
||||||
CVector3D& CVector3D::operator *= (float value)
|
|
||||||
{
|
|
||||||
X *= value;
|
|
||||||
Y *= value;
|
|
||||||
Z *= value;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVector3D::Set (float x, float y, float z)
|
|
||||||
{
|
|
||||||
X = x;
|
|
||||||
Y = y;
|
|
||||||
Z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVector3D::Clear ()
|
|
||||||
{
|
|
||||||
X = Y = Z = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CVector3D::operator==( const CVector3D& vector ) const
|
|
||||||
{
|
|
||||||
return( ( X == vector.X ) && ( Y == vector.Y ) && ( Z == vector.Z ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//Dot product
|
|
||||||
float CVector3D::Dot (const CVector3D &vector) const
|
|
||||||
{
|
|
||||||
return ( X * vector.X +
|
|
||||||
Y * vector.Y +
|
|
||||||
Z * vector.Z );
|
|
||||||
}
|
|
||||||
|
|
||||||
//Cross product
|
|
||||||
CVector3D CVector3D::Cross (const CVector3D &vector) const
|
|
||||||
{
|
|
||||||
CVector3D Temp;
|
|
||||||
|
|
||||||
Temp.X = (Y * vector.Z) - (Z * vector.Y);
|
|
||||||
Temp.Y = (Z * vector.X) - (X * vector.Z);
|
|
||||||
Temp.Z = (X * vector.Y) - (Y * vector.X);
|
|
||||||
|
|
||||||
return Temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
float CVector3D::GetLength () const
|
|
||||||
{
|
|
||||||
return sqrtf ( SQR(X) + SQR(Y) + SQR(Z) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVector3D::Normalize ()
|
|
||||||
{
|
|
||||||
float scale = 1.0f/GetLength ();
|
|
||||||
|
|
||||||
X *= scale;
|
|
||||||
Y *= scale;
|
|
||||||
Z *= scale;
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: Vector3D.H
|
|
||||||
// Last Update: 28/1/02
|
|
||||||
// Author: Poya Manouchehri
|
|
||||||
//
|
|
||||||
// Description: Provides an interface for a vector in R3 and
|
|
||||||
// allows vector and scalar operations on it
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef VECTOR3D_H
|
|
||||||
#define VECTOR3D_H
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include "res/res.h"
|
|
||||||
#include "MathUtil.h"
|
|
||||||
|
|
||||||
class CVector3D
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
float X, Y, Z;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CVector3D () { }
|
|
||||||
CVector3D (float x, float y, float z);
|
|
||||||
|
|
||||||
int operator ! () const ;
|
|
||||||
|
|
||||||
float& operator[](int index) { return *((&X)+index); }
|
|
||||||
const float& operator[](int index) const { return *((&X)+index); }
|
|
||||||
|
|
||||||
//vector addition
|
|
||||||
CVector3D operator + (const CVector3D &vector) const ;
|
|
||||||
//vector addition/assignment
|
|
||||||
CVector3D &operator += (const CVector3D &vector);
|
|
||||||
|
|
||||||
//vector subtraction
|
|
||||||
CVector3D operator - (const CVector3D &vector) const ;
|
|
||||||
//vector subtraction/assignment
|
|
||||||
CVector3D &operator -= (const CVector3D &vector);
|
|
||||||
|
|
||||||
//scalar multiplication
|
|
||||||
CVector3D operator * (float value) const ;
|
|
||||||
//scalar multiplication/assignment
|
|
||||||
CVector3D& operator *= (float value);
|
|
||||||
|
|
||||||
// negation
|
|
||||||
CVector3D operator-() const;
|
|
||||||
|
|
||||||
bool operator==( const CVector3D& vector ) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Set (float x, float y, float z);
|
|
||||||
void Clear ();
|
|
||||||
|
|
||||||
//Dot product
|
|
||||||
float Dot (const CVector3D &vector) const;
|
|
||||||
//Cross product
|
|
||||||
CVector3D Cross (const CVector3D &vector) const;
|
|
||||||
|
|
||||||
//Returns length of the vector
|
|
||||||
float GetLength () const;
|
|
||||||
void Normalize ();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,110 +0,0 @@
|
|||||||
//***********************************************************
|
|
||||||
//
|
|
||||||
// Name: CVector4D.h
|
|
||||||
// Last Update: 02/11/03
|
|
||||||
// Author: Rich Cross
|
|
||||||
//
|
|
||||||
// Description: Provides an interface for a vector in R4 and
|
|
||||||
// allows vector and scalar operations on it
|
|
||||||
//
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
#ifndef _VECTOR4D_H
|
|
||||||
#define _VECTOR4D_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CVector4D:
|
|
||||||
class CVector4D
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CVector4D() {}
|
|
||||||
CVector4D(const float f[4]) { m_X=f[0]; m_Y=f[1]; m_Z=f[2]; m_W=f[3]; }
|
|
||||||
CVector4D(float x,float y,float z,float w) { m_X=x; m_Y=y; m_Z=z; m_W=w; }
|
|
||||||
CVector4D(const CVector4D& p) { m_X=p.m_X; m_Y=p.m_Y; m_Z=p.m_Z; m_W=p.m_W; }
|
|
||||||
|
|
||||||
operator float*() {
|
|
||||||
return &m_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator const float*() const {
|
|
||||||
return &m_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator-() const {
|
|
||||||
return CVector4D(-m_X,-m_Y,-m_Z,-m_W);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator+(const CVector4D& t) const {
|
|
||||||
return CVector4D(m_X+t.m_X,m_Y+t.m_Y,m_Z+t.m_Z,m_W+t.m_W);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator-(const CVector4D& t) const {
|
|
||||||
return CVector4D(m_X-t.m_X,m_Y-t.m_Y,m_Z-t.m_Z,m_W-t.m_W);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator*(const CVector4D& t) const {
|
|
||||||
return CVector4D(m_X*t.m_X,m_Y*t.m_Y,m_Z*t.m_Z,m_W*t.m_W);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator*(float f) const {
|
|
||||||
return CVector4D(m_X*f,m_Y*f,m_Z*f,m_W*f);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D operator/(float f) const {
|
|
||||||
float inv=1.0f/f;
|
|
||||||
return CVector4D(m_X*inv,m_Y*inv,m_Z*inv,m_W*inv);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D& operator+=(const CVector4D& t) {
|
|
||||||
m_X+=t.m_X; m_Y+=t.m_Y; m_Z+=t.m_Z; m_W+=t.m_W;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D& operator-=(const CVector4D& t) {
|
|
||||||
m_X-=t.m_X; m_Y-=t.m_Y; m_Z-=t.m_Z; m_W-=t.m_W;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D& operator*=(const CVector4D& t) {
|
|
||||||
m_X*=t.m_X; m_Y*=t.m_Y; m_Z*=t.m_Z; m_W*=t.m_W;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D& operator*=(float f) {
|
|
||||||
m_X*=f; m_Y*=f; m_Z*=f; m_W*=f;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector4D& operator/=(float f) {
|
|
||||||
float invf=1.0f/f;
|
|
||||||
m_X*=invf; m_Y*=invf; m_Z*=invf; m_W*=invf;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
float dot(const CVector4D& a) const {
|
|
||||||
return m_X*a.m_X+m_Y*a.m_Y+m_Z*a.m_Z+m_W*a.m_W;
|
|
||||||
}
|
|
||||||
|
|
||||||
float lengthSquared() const {
|
|
||||||
return SQR(m_X)+SQR(m_Y)+SQR(m_Z)+SQR(m_W);
|
|
||||||
}
|
|
||||||
|
|
||||||
float length() const {
|
|
||||||
return (float) sqrt(lengthSquared());
|
|
||||||
}
|
|
||||||
|
|
||||||
void normalize() {
|
|
||||||
float mag=length();
|
|
||||||
m_X/=mag; m_Y/=mag; m_Z/=mag; m_W/=mag;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
float m_X,m_Y,m_Z,m_W;
|
|
||||||
};
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user