This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View File

@@ -0,0 +1,662 @@
#include "RenderPCH.h"
#pragma warning(push)
#pragma warning(disable:4244) // conversion from 'double' to 'float', possible loss of data
#pragma warning(disable:4305) // truncation from 'double' to 'float'
void utlMtx2Euler(int ord, float m[3][3], float rot[3]);
static void utlMtx2Quat(float m[3][3], float quat[4]);
// ========== utlDecompMatrix ==========
//
// SYNOPSIS
// Decompose a matrix to it's components, translate,
// rotate ( a quaternion) and scale.
//
static void utlDecompMatrix( const float *mat, DECOMP_MAT *dmat, char *rotOrder)
{
int i, j,
order;
static float Sxy, Sxz,
rot[3], quat[4],
det,
m[3][3];
dmat->translate[0] = mat[3*4+0];
dmat->translate[1] = mat[3*4+1];
dmat->translate[2] = mat[3*4+2];
m[0][0] = mat[0*4+0];
m[0][1] = mat[0*4+1];
m[0][2] = mat[0*4+2];
dmat->scale[0] = sqrt_tpl( m[0][0]*m[0][0] + m[0][1]*m[0][1] + m[0][2]*m[0][2]);
/* Normalize second row */
m[0][0] /= dmat->scale[0];
m[0][1] /= dmat->scale[0];
m[0][2] /= dmat->scale[0];
/* Determine xy shear */
Sxy = mat[0*4+0] * mat[1*4+0] +
mat[0*4+1] * mat[1*4+1] +
mat[0*4+2] * mat[1*4+2];
m[1][0] = mat[1*4+0] - Sxy * mat[0*4+0];
m[1][1] = mat[1*4+1] - Sxy * mat[0*4+1];
m[1][2] = mat[1*4+2] - Sxy * mat[0*4+2];
dmat->scale[1] = sqrt_tpl( m[1][0]*m[1][0] + m[1][1]*m[1][1] + m[1][2]*m[1][2]);
/* Normalize second row */
m[1][0] /= dmat->scale[1];
m[1][1] /= dmat->scale[1];
m[1][2] /= dmat->scale[1];
/* Determine xz shear */
Sxz = mat[0*4+0] * mat[2*4+0] +
mat[0*4+1] * mat[2*4+1] +
mat[0*4+2] * mat[2*4+2];
m[2][0] = mat[2*4+0] - Sxz * mat[0*4+0];
m[2][1] = mat[2*4+1] - Sxz * mat[0*4+1];
m[2][2] = mat[2*4+2] - Sxz * mat[0*4+2];
dmat->scale[2] = sqrt_tpl( m[2][0]*m[2][0] + m[2][1]*m[2][1] + m[2][2]*m[2][2]);
/* Normalize third row */
m[2][0] /= dmat->scale[2];
m[2][1] /= dmat->scale[2];
m[2][2] /= dmat->scale[2];
det = (m[0][0]*m[1][1]*m[2][2]) + (m[0][1]*m[1][2]*m[2][0]) + (m[0][2]*m[1][0]*m[2][1]) -
(m[0][2]*m[1][1]*m[2][0]) - (m[0][0]*m[1][2]*m[2][1]) - (m[0][1]*m[1][0]*m[2][2]);
/* If the determinant of the rotation matrix is negative, */
/* negate the matrix and scale factors. */
if ( det < 0.0) {
for ( i = 0; i < 3; i++) {
for ( j = 0; j < 3; j++)
m[i][j] *= -1.0;
dmat->scale[i] *= -1.0;
}
}
// Copy the 3x3 rotation matrix into the decomposition
// structure.
//
memcpy( dmat->rotMatrix, m, sizeof( float)*9);
/*rot[1] = asin( -m[0][2]);
if ( fabsf( cos( rot[1])) > 0.0001) {
rot[0] = asin( m[1][2]/cos( rot[1]));
rot[2] = asin( m[0][1]/cos( rot[1]));
} else {
rot[0] = acos( m[1][1]);
rot[2] = 0.0;
}*/
switch( rotOrder[2]) {
case XROT:
if ( rotOrder[1] == YROT)
order = UTL_ROT_XYZ;
else
order = UTL_ROT_XZY;
break;
case YROT:
if ( rotOrder[1] == XROT)
order = UTL_ROT_YXZ;
else
order = UTL_ROT_YZX;
break;
case ZROT:
if ( rotOrder[1] == XROT)
order = UTL_ROT_ZXY;
else
order = UTL_ROT_ZYX;
break;
default:
order = UTL_ROT_XYZ;
break;
}
utlMtx2Euler( order, m, rot);
dmat->rotation[0] = rot[0];
dmat->rotation[1] = rot[1];
dmat->rotation[2] = rot[2];
utlMtx2Quat(m,quat);
dmat->quaternion[0] = quat[0];
dmat->quaternion[1] = quat[1];
dmat->quaternion[2] = quat[2];
dmat->quaternion[3] = quat[3];
}
/*
* ========== CapQuat2Euler ==========
*
* SYNOPSIS
* Convert a quaternion to Euler angles.
*
* PARAMETERS
* int The order of rotations
* float mat[3][3] rotation matrix
* float rot[3] xyz-rotation values
*
* DESCRIPTION
* This routine converts a mateix to Euler angles.
* There are a few caveats:
* The rotation order for the returned angles is always zyx.
* The derivation of this algorithm is taken from Ken Shoemake's
* paper:
* SIGGRAPH 1985, Vol. 19, # 3, pp. 253-254
*
* RETURN VALUE
* None.
*/
#ifdef WIN32
#define M_PI_2 3.14159/2.0
#endif
void utlMtx2Euler(int ord, float m[3][3], float rot[3])
{
/*
* Ken Shoemake's recommended algorithm is to convert the
* quaternion to a matrix and the matrix to Euler angles.
* We do this, of course, without generating unused matrix
* elements.
*/
float zr, sxr, cxr,
yr, syr, cyr,
xr, szr, czr;
static float epsilon = 1.0e-5f;
switch ( ord) {
case UTL_ROT_ZYX:
syr = -m[0][2];
cyr = sqrt_tpl(1 - syr * syr);
if (cyr < epsilon) {
/* Insufficient accuracy, assume that yr = PI/2 && zr = 0 */
xr = cry_atan2f(-m[2][1], m[1][1]);
yr = (syr > 0) ? M_PI_2 : -M_PI_2; /* +/- 90 deg */
zr = 0.0;
} else {
xr = cry_atan2f(m[1][2], m[2][2]);
yr = cry_atan2f(syr, cyr);
zr = cry_atan2f(m[0][1], m[0][0]);
}
break;
case UTL_ROT_YZX:
szr = m[0][1];
czr = sqrt_tpl(1 - szr * szr);
if (czr < epsilon) {
/* Insufficient accuracy, assume that zr = +/- PI/2 && yr = 0 */
xr = cry_atan2f(m[1][2], m[2][2]);
yr = 0.0;
zr = (szr > 0) ? M_PI_2 : -M_PI_2;
} else {
xr = cry_atan2f(-m[2][1], m[1][1]);
yr = cry_atan2f(-m[0][2], m[0][0]);
zr = cry_atan2f(szr, czr);
}
break;
case UTL_ROT_ZXY:
sxr = m[1][2];
cxr = sqrt_tpl(1 - sxr * sxr);
if (cxr < epsilon) {
/* Insufficient accuracy, assume that xr = PI/2 && zr = 0 */
xr = (sxr > 0) ? M_PI_2 : -M_PI_2;
yr = cry_atan2f(m[2][0], m[0][0]);
zr = 0.0;
} else {
xr = cry_atan2f( sxr, cxr);
yr = cry_atan2f(-m[0][2], m[2][2]);
zr = cry_atan2f(-m[1][0], m[1][1]);
}
break;
case UTL_ROT_XZY:
szr = -m[1][0];
czr = sqrt_tpl(1 - szr * szr);
if (czr < epsilon) {
/* Insufficient accuracy, assume that zr = PI / 2 && xr = 0 */
xr = 0.0;
yr = cry_atan2f(-m[0][2], m[2][2]);
zr = (szr > 0) ? M_PI_2 : -M_PI_2;
} else {
xr = cry_atan2f(m[0][2], m[1][1]);
yr = cry_atan2f(m[2][0], m[0][0]);
zr = cry_atan2f(szr, czr);
}
break;
case UTL_ROT_YXZ:
sxr = -m[2][1];
cxr = sqrt_tpl(1 - sxr * sxr);
if (cxr < epsilon) {
/* Insufficient accuracy, assume that xr = PI/2 && yr = 0 */
xr = (sxr > 0) ? M_PI_2 : -M_PI_2;
yr = 0.0;
zr = cry_atan2f(-m[1][0], m[0][0]);
} else {
xr = cry_atan2f(sxr, cxr);
yr = cry_atan2f(m[2][0], m[2][2]);
zr = cry_atan2f(m[0][1], m[1][1]);
}
break;
case UTL_ROT_XYZ:
syr = m[2][0];
cyr = sqrt_tpl(1 - syr * syr);
if (cyr < epsilon) {
/* Insufficient accuracy, assume that yr = PI / 2 && xr = 0 */
xr = 0.0;
yr = (syr > 0) ? M_PI_2 : -M_PI_2;
zr = cry_atan2f(m[0][1], m[1][1]);
} else {
xr = cry_atan2f(-m[2][1], m[2][2]);
yr = cry_atan2f( syr, cyr);
zr = cry_atan2f(-m[1][1], m[0][0]);
}
break;
}
rot[0] = xr;
rot[1] = yr;
rot[2] = zr;
}
/*
* ========= utlMtx2Quat ====================
*
* SYNOPSIS
* Returns the w,x,y,z coordinates of the quaternion
* given the rotation matrix.
*/
static void utlMtx2Quat(float m[3][3], float quat[4])
{
// m stores the 3x3 rotation matrix.
// Convert it to quaternion.
float trace = m[0][0] + m[1][1] + m[2][2];
float s;
if (trace > 0.0) {
s = sqrt_tpl(trace + 1.0);
quat[0] = s*0.5;
s = 0.5/s;
quat[1] = (m[1][2] - m[2][1])*s;
quat[2] = (m[2][0] - m[0][2])*s;
quat[3] = (m[0][1] - m[1][0])*s;
}
else {
int i = 0; // i represents index of quaternion, so 0=scalar, 1=xaxis, etc.
int nxt[3] = {1,2,0}; // next index for each component.
if (m[1][1] > m[0][0]) i = 1;
if (m[2][2] > m[i][i]) i = 2;
int j = nxt[i]; int k = nxt[j];
s = sqrt_tpl( (m[i][i] - (m[j][j] + m[k][k])) + 1.0);
float q[4];
q[i+1] = s*0.5;
s=0.5/s;
q[0] = (m[j][k] - m[k][j])*s;
q[j+1] = (m[i][j]+m[j][i])*s;
q[k+1] = (m[i][k]+m[k][i])*s;
quat[0] = q[0];
quat[1] = q[1];
quat[2] = q[2];
quat[3] = q[3];
}
}
/*
* ========== DtMatrixGetTranslation ==========
*
* SYNOPSIS
* Return the x,y,z translation components of the
* given matrix. The priority order is assumed to be ---.
*/
int DtMatrixGetTranslation( float *matrix, float *xTrans, float *yTrans, float *zTrans)
{
DECOMP_MAT dmat;
if (matrix)
{
utlDecompMatrix( matrix, &dmat, "xyz" );
*xTrans = dmat.translate[0];
*yTrans = dmat.translate[1];
*zTrans = dmat.translate[2];
}
else
{
*xTrans = *yTrans = *zTrans = 0.0;
}
return(1);
} /* DtMatrixGetTranslation */
/*
* ========== DtMatrixGetQuaternion ==========
*
* SYNOPSIS
* Return the quaternion (scalar, xAxis, yAxis, zAxis)
* defining the orientation represented in the given matrix.
*/
int DtMatrixGetQuaternion(float *matrix, float *scalar, float *xAxis, float *yAxis, float *zAxis)
{
DECOMP_MAT dmat;
if (matrix)
{
utlDecompMatrix( matrix, &dmat, "xyz" );
*scalar = dmat.quaternion[0];
*xAxis = dmat.quaternion[1];
*yAxis = dmat.quaternion[2];
*zAxis = dmat.quaternion[3];
}
else
{
*scalar = 1.0; *xAxis = *yAxis = *zAxis = 0.0;
}
return(1);
} /* DtMatrixGetQuaternion */
/*
* ========== DtMatrixGetRotation ==========
*
* SYNOPSIS
* Return the x,y,z rotation components of the
* given matrix. The priority order is assumed to be ---.
*/
int DtMatrixGetRotation(float *matrix, float *xRotation, float *yRotation, float *zRotation)
{
DECOMP_MAT dmat;
if (matrix)
{
utlDecompMatrix( matrix, &dmat, "xyz" );
*xRotation = dmat.rotation[0];
*yRotation = dmat.rotation[1];
*zRotation = dmat.rotation[2];
}
else
{
*xRotation = *yRotation = *zRotation = 0.0;
}
return(1);
} /* DtMatrixGetRotation */
/*
* ========== DtMatrixGetScale ==========
*
* SYNOPSIS
* Return the x,y,z scale components of the given
* matrix. The priority order is assumed to be ---.
*/
int DtMatrixGetScale(float *matrix, float *xScale, float *yScale, float *zScale)
{
DECOMP_MAT dmat;
if (matrix)
{
utlDecompMatrix( matrix, &dmat, "xyz" );
*xScale = dmat.scale[0];
*yScale = dmat.scale[1];
*zScale = dmat.scale[2];
}
else
{
*xScale = *yScale = *zScale = 1.0;
}
return(1);
} /* DtMatrixGetScale */
/*
* ========== DtMatrixGetTransforms ==========
*
* SYNOPSIS
* Return the x,y,z translation, scale quaternion and
* Euler angles in "xyz" order of the given
* matrix.
*/
int DtMatrixGetTransforms(float *matrix, float *translate,
float *scale, float *quaternion, float *rotation)
{
DECOMP_MAT dmat;
if (matrix)
{
utlDecompMatrix( matrix, &dmat, "xyz" );
if (translate) {
translate[0] = dmat.translate[0];
translate[1] = dmat.translate[1];
translate[2] = dmat.translate[2];
}
if (scale) {
scale[0] = dmat.scale[0];
scale[1] = dmat.scale[1];
scale[2] = dmat.scale[2];
}
if (quaternion) {
quaternion[0] = dmat.quaternion[0];
quaternion[1] = dmat.quaternion[1];
quaternion[2] = dmat.quaternion[2];
quaternion[3] = dmat.quaternion[3];
}
if (rotation) {
rotation[0] = dmat.rotation[0];
rotation[1] = dmat.rotation[1];
rotation[2] = dmat.rotation[2];
}
return(1);
}
return(0);
}
//==============================================================================
float gSinTable[1024] = {
0.000000,0.001534,0.003068,0.004602,0.006136,0.007670,0.009204,0.010738,
0.012272,0.013805,0.015339,0.016873,0.018407,0.019940,0.021474,0.023008,
0.024541,0.026075,0.027608,0.029142,0.030675,0.032208,0.033741,0.035274,
0.036807,0.038340,0.039873,0.041406,0.042938,0.044471,0.046003,0.047535,
0.049068,0.050600,0.052132,0.053664,0.055195,0.056727,0.058258,0.059790,
0.061321,0.062852,0.064383,0.065913,0.067444,0.068974,0.070505,0.072035,
0.073565,0.075094,0.076624,0.078153,0.079682,0.081211,0.082740,0.084269,
0.085797,0.087326,0.088854,0.090381,0.091909,0.093436,0.094963,0.096490,
0.098017,0.099544,0.101070,0.102596,0.104122,0.105647,0.107172,0.108697,
0.110222,0.111747,0.113271,0.114795,0.116319,0.117842,0.119365,0.120888,
0.122411,0.123933,0.125455,0.126977,0.128498,0.130019,0.131540,0.133061,
0.134581,0.136101,0.137620,0.139139,0.140658,0.142177,0.143695,0.145213,
0.146730,0.148248,0.149765,0.151281,0.152797,0.154313,0.155828,0.157343,
0.158858,0.160372,0.161886,0.163400,0.164913,0.166426,0.167938,0.169450,
0.170962,0.172473,0.173984,0.175494,0.177004,0.178514,0.180023,0.181532,
0.183040,0.184548,0.186055,0.187562,0.189069,0.190575,0.192080,0.193586,
0.195090,0.196595,0.198098,0.199602,0.201105,0.202607,0.204109,0.205610,
0.207111,0.208612,0.210112,0.211611,0.213110,0.214609,0.216107,0.217604,
0.219101,0.220598,0.222094,0.223589,0.225084,0.226578,0.228072,0.229565,
0.231058,0.232550,0.234042,0.235533,0.237024,0.238514,0.240003,0.241492,
0.242980,0.244468,0.245955,0.247442,0.248928,0.250413,0.251898,0.253382,
0.254866,0.256349,0.257831,0.259313,0.260794,0.262275,0.263755,0.265234,
0.266713,0.268191,0.269668,0.271145,0.272621,0.274097,0.275572,0.277046,
0.278520,0.279993,0.281465,0.282937,0.284408,0.285878,0.287347,0.288816,
0.290285,0.291752,0.293219,0.294685,0.296151,0.297616,0.299080,0.300543,
0.302006,0.303468,0.304929,0.306390,0.307850,0.309309,0.310767,0.312225,
0.313682,0.315138,0.316593,0.318048,0.319502,0.320955,0.322408,0.323859,
0.325310,0.326760,0.328210,0.329658,0.331106,0.332553,0.334000,0.335445,
0.336890,0.338334,0.339777,0.341219,0.342661,0.344101,0.345541,0.346980,
0.348419,0.349856,0.351293,0.352729,0.354164,0.355598,0.357031,0.358463,
0.359895,0.361326,0.362756,0.364185,0.365613,0.367040,0.368467,0.369892,
0.371317,0.372741,0.374164,0.375586,0.377007,0.378428,0.379847,0.381266,
0.382683,0.384100,0.385516,0.386931,0.388345,0.389758,0.391170,0.392582,
0.393992,0.395401,0.396810,0.398218,0.399624,0.401030,0.402435,0.403838,
0.405241,0.406643,0.408044,0.409444,0.410843,0.412241,0.413638,0.415034,
0.416430,0.417824,0.419217,0.420609,0.422000,0.423390,0.424780,0.426168,
0.427555,0.428941,0.430326,0.431711,0.433094,0.434476,0.435857,0.437237,
0.438616,0.439994,0.441371,0.442747,0.444122,0.445496,0.446869,0.448241,
0.449611,0.450981,0.452350,0.453717,0.455084,0.456449,0.457813,0.459177,
0.460539,0.461900,0.463260,0.464619,0.465976,0.467333,0.468689,0.470043,
0.471397,0.472749,0.474100,0.475450,0.476799,0.478147,0.479494,0.480839,
0.482184,0.483527,0.484869,0.486210,0.487550,0.488889,0.490226,0.491563,
0.492898,0.494232,0.495565,0.496897,0.498228,0.499557,0.500885,0.502212,
0.503538,0.504863,0.506187,0.507509,0.508830,0.510150,0.511469,0.512786,
0.514103,0.515418,0.516732,0.518045,0.519356,0.520666,0.521975,0.523283,
0.524590,0.525895,0.527199,0.528502,0.529804,0.531104,0.532403,0.533701,
0.534998,0.536293,0.537587,0.538880,0.540171,0.541462,0.542751,0.544039,
0.545325,0.546610,0.547894,0.549177,0.550458,0.551738,0.553017,0.554294,
0.555570,0.556845,0.558119,0.559391,0.560662,0.561931,0.563199,0.564466,
0.565732,0.566996,0.568259,0.569521,0.570781,0.572040,0.573297,0.574553,
0.575808,0.577062,0.578314,0.579565,0.580814,0.582062,0.583309,0.584554,
0.585798,0.587040,0.588282,0.589521,0.590760,0.591997,0.593232,0.594466,
0.595699,0.596931,0.598161,0.599389,0.600616,0.601842,0.603067,0.604290,
0.605511,0.606731,0.607950,0.609167,0.610383,0.611597,0.612810,0.614022,
0.615232,0.616440,0.617647,0.618853,0.620057,0.621260,0.622461,0.623661,
0.624859,0.626056,0.627252,0.628446,0.629638,0.630829,0.632019,0.633207,
0.634393,0.635578,0.636762,0.637944,0.639124,0.640303,0.641481,0.642657,
0.643832,0.645005,0.646176,0.647346,0.648514,0.649681,0.650847,0.652011,
0.653173,0.654334,0.655493,0.656651,0.657807,0.658961,0.660114,0.661266,
0.662416,0.663564,0.664711,0.665856,0.667000,0.668142,0.669283,0.670422,
0.671559,0.672695,0.673829,0.674962,0.676093,0.677222,0.678350,0.679476,
0.680601,0.681724,0.682846,0.683965,0.685084,0.686200,0.687315,0.688429,
0.689541,0.690651,0.691759,0.692866,0.693971,0.695075,0.696177,0.697278,
0.698376,0.699473,0.700569,0.701663,0.702755,0.703845,0.704934,0.706021,
0.707107,0.708191,0.709273,0.710353,0.711432,0.712509,0.713585,0.714659,
0.715731,0.716801,0.717870,0.718937,0.720003,0.721066,0.722128,0.723188,
0.724247,0.725304,0.726359,0.727413,0.728464,0.729514,0.730563,0.731609,
0.732654,0.733697,0.734739,0.735779,0.736817,0.737853,0.738887,0.739920,
0.740951,0.741980,0.743008,0.744034,0.745058,0.746080,0.747101,0.748119,
0.749136,0.750152,0.751165,0.752177,0.753187,0.754195,0.755201,0.756206,
0.757209,0.758210,0.759209,0.760207,0.761202,0.762196,0.763188,0.764179,
0.765167,0.766154,0.767139,0.768122,0.769103,0.770083,0.771061,0.772036,
0.773010,0.773983,0.774953,0.775922,0.776888,0.777853,0.778817,0.779778,
0.780737,0.781695,0.782651,0.783605,0.784557,0.785507,0.786455,0.787402,
0.788346,0.789289,0.790230,0.791169,0.792107,0.793042,0.793975,0.794907,
0.795837,0.796765,0.797691,0.798615,0.799537,0.800458,0.801376,0.802293,
0.803208,0.804120,0.805031,0.805940,0.806848,0.807753,0.808656,0.809558,
0.810457,0.811355,0.812251,0.813144,0.814036,0.814926,0.815814,0.816701,
0.817585,0.818467,0.819348,0.820226,0.821103,0.821977,0.822850,0.823721,
0.824589,0.825456,0.826321,0.827184,0.828045,0.828904,0.829761,0.830616,
0.831470,0.832321,0.833170,0.834018,0.834863,0.835706,0.836548,0.837387,
0.838225,0.839060,0.839894,0.840725,0.841555,0.842383,0.843208,0.844032,
0.844854,0.845673,0.846491,0.847307,0.848120,0.848932,0.849742,0.850549,
0.851355,0.852159,0.852961,0.853760,0.854558,0.855354,0.856147,0.856939,
0.857729,0.858516,0.859302,0.860085,0.860867,0.861646,0.862424,0.863199,
0.863973,0.864744,0.865514,0.866281,0.867046,0.867809,0.868571,0.869330,
0.870087,0.870842,0.871595,0.872346,0.873095,0.873842,0.874587,0.875329,
0.876070,0.876809,0.877545,0.878280,0.879012,0.879743,0.880471,0.881197,
0.881921,0.882643,0.883363,0.884081,0.884797,0.885511,0.886223,0.886932,
0.887640,0.888345,0.889048,0.889750,0.890449,0.891146,0.891841,0.892534,
0.893224,0.893913,0.894599,0.895284,0.895966,0.896646,0.897325,0.898001,
0.898674,0.899346,0.900016,0.900683,0.901349,0.902012,0.902673,0.903332,
0.903989,0.904644,0.905297,0.905947,0.906596,0.907242,0.907886,0.908528,
0.909168,0.909806,0.910441,0.911075,0.911706,0.912335,0.912962,0.913587,
0.914210,0.914830,0.915449,0.916065,0.916679,0.917291,0.917901,0.918508,
0.919114,0.919717,0.920318,0.920917,0.921514,0.922109,0.922701,0.923291,
0.923880,0.924465,0.925049,0.925631,0.926210,0.926787,0.927363,0.927935,
0.928506,0.929075,0.929641,0.930205,0.930767,0.931327,0.931884,0.932440,
0.932993,0.933544,0.934093,0.934639,0.935184,0.935726,0.936266,0.936803,
0.937339,0.937872,0.938404,0.938932,0.939459,0.939984,0.940506,0.941026,
0.941544,0.942060,0.942573,0.943084,0.943593,0.944100,0.944605,0.945107,
0.945607,0.946105,0.946601,0.947094,0.947586,0.948075,0.948561,0.949046,
0.949528,0.950008,0.950486,0.950962,0.951435,0.951906,0.952375,0.952842,
0.953306,0.953768,0.954228,0.954686,0.955141,0.955594,0.956045,0.956494,
0.956940,0.957385,0.957826,0.958266,0.958703,0.959139,0.959572,0.960002,
0.960431,0.960857,0.961280,0.961702,0.962121,0.962538,0.962953,0.963366,
0.963776,0.964184,0.964590,0.964993,0.965394,0.965793,0.966190,0.966584,
0.966976,0.967366,0.967754,0.968139,0.968522,0.968903,0.969281,0.969657,
0.970031,0.970403,0.970772,0.971139,0.971504,0.971866,0.972226,0.972584,
0.972940,0.973293,0.973644,0.973993,0.974339,0.974684,0.975025,0.975365,
0.975702,0.976037,0.976370,0.976700,0.977028,0.977354,0.977677,0.977999,
0.978317,0.978634,0.978948,0.979260,0.979570,0.979877,0.980182,0.980485,
0.980785,0.981083,0.981379,0.981673,0.981964,0.982253,0.982539,0.982824,
0.983105,0.983385,0.983662,0.983937,0.984210,0.984480,0.984749,0.985014,
0.985278,0.985539,0.985798,0.986054,0.986308,0.986560,0.986809,0.987057,
0.987301,0.987544,0.987784,0.988022,0.988258,0.988491,0.988722,0.988950,
0.989177,0.989400,0.989622,0.989841,0.990058,0.990273,0.990485,0.990695,
0.990903,0.991108,0.991311,0.991511,0.991710,0.991906,0.992099,0.992291,
0.992480,0.992666,0.992850,0.993032,0.993212,0.993389,0.993564,0.993737,
0.993907,0.994075,0.994240,0.994404,0.994565,0.994723,0.994879,0.995033,
0.995185,0.995334,0.995481,0.995625,0.995767,0.995907,0.996045,0.996180,
0.996313,0.996443,0.996571,0.996697,0.996820,0.996941,0.997060,0.997176,
0.997290,0.997402,0.997511,0.997618,0.997723,0.997825,0.997925,0.998023,
0.998118,0.998211,0.998302,0.998390,0.998476,0.998559,0.998640,0.998719,
0.998795,0.998870,0.998941,0.999011,0.999078,0.999142,0.999205,0.999265,
0.999322,0.999378,0.999431,0.999481,0.999529,0.999575,0.999619,0.999660,
0.999699,0.999735,0.999769,0.999801,0.999831,0.999858,0.999882,0.999905,
0.999925,0.999942,0.999958,0.999971,0.999981,0.999989,0.999995,0.999999
};
typedef union FastSqrtUnion
{
float f;
unsigned int i;
} FastSqrtUnion;
unsigned int gFastSqrtTable[0x10000]; // declare table of square roots
void build_sqrt_table()
{
unsigned int i;
FastSqrtUnion s;
for (i = 0; i <= 0x7FFF; i++)
{
// Build a float with the bit pattern i as mantissa
// and an exponent of 0, stored as 127
s.i = (i << 8) | (0x7F << 23);
s.f = (float)sqrt_tpl(s.f);
// Take the square root then strip the first 7 bits of
// the mantissa into the table
gFastSqrtTable[i + 0x8000] = (s.i & 0x7FFFFF);
// Repeat the process, this time with an exponent of 1,
// stored as 128
s.i = (i << 8) | (0x80 << 23);
s.f = (float)sqrt_tpl(s.f);
gFastSqrtTable[i] = (s.i & 0x7FFFFF);
}
}
#include <float.h>
/*
* Initialize tables, etc for fast math functions.
*/
void init_math(void)
{
static bool initialized = false;
if (!initialized)
{
build_sqrt_table();
initialized = true;
}
}
#pragma warning(pop)

View File

@@ -0,0 +1,55 @@
//==============================================================================
//
// 3D math file
//
//==============================================================================
#ifndef __3DUTILS_H__
#define __3DUTILS_H__
#include <math.h>
typedef struct {
float translate[3];
float scale[3];
float rotation[3]; /* Euler angles */
float quaternion[4]; /* quaternion */
float rotMatrix[3][3]; /* rotation matrix */
} DECOMP_MAT;
#define UTL_ROT_XYZ 0
#define UTL_ROT_XZY 1
#define UTL_ROT_YXZ 2
#define UTL_ROT_YZX 3
#define UTL_ROT_ZXY 4
#define UTL_ROT_ZYX 5
#define XROT 'x'
#define YROT 'y'
#define ZROT 'z'
void utlMtx2Euler(int ord, float m[3][3], float rot[3]);
int DtMatrixGetTransforms(float *matrix, float *translate, float *scale, float *quaternion, float *rotation);
void init_math(void);
//==========================================================================
#define FP_BITS(fp) (*(DWORD *)&(fp))
extern unsigned int gFastSqrtTable[0x10000]; // declare table of square roots
extern float gSinTable[1024];
_inline float crySqrtf(float n)
{
if (FP_BITS(n) == 0)
return 0.0; // check for square root of 0
FP_BITS(n) = gFastSqrtTable[(FP_BITS(n) >> 8) & 0xFFFF] | ((((FP_BITS(n) - 0x3F800000) >> 1) + 0x3F800000) & 0x7F800000);
return n;
}
#endif

View File

@@ -0,0 +1,92 @@
//
// Header file for compression library
//
#ifndef _COMPRESSORLIB_H
#define _COMPRESSORLIB_H
#ifdef __cplusplus
extern "C"
{
#endif
#if defined(LINUX)
#define _stdcall
#else
#include "Windows.h"
#endif
typedef enum
{
FORMAT_COMP_ATI2N,
FORMAT_COMP_ATI2N_DXT5,
FORMAT_COMP_TOOBIG
} COMPRESSED_FORMAT;
typedef enum
{
FORMAT_ARGB_8888,
FORMAT_ARGB_TOOBIG
} UNCOMPRESSED_FORMAT;
typedef enum
{
COMPRESSOR_ERROR_NONE,
COMPRESSOR_ERROR_NO_INPUT_DATA,
COMPRESSOR_ERROR_NO_OUTPUT_POINTER,
COMPRESSOR_ERROR_UNSUPPORTED_SOURCE_FORMAT,
COMPRESSOR_ERROR_UNSUPPORTED_DESTINATION_FORMAT,
COMPRESSOR_ERROR_UNABLE_TO_INIT_CODEC,
COMPRESSOR_ERROR_GENERIC
} COMPRESSOR_ERROR;
//
// Compressor entry point
//
// Parameters -
//
// width - width of input image in pixels
// height - height of input image in pixels
// sourceFormat - format of source texture (must be ARGB_8888 at the moment)
// destinationFormat - format of output texture (can be ATI2N or ATI2N_DXT5)
// inputData - pointer to uncompressed texture data
// dataOut - address of pointer that will point to the compressed data
// outDataSize - filled with the size of the compressed data buffer (can be NULL)
//
COMPRESSOR_ERROR _stdcall CompressTexture(DWORD width,
DWORD height,
UNCOMPRESSED_FORMAT sourceFormat,
COMPRESSED_FORMAT destinationFormat,
void *inputData,
void **dataOut,
DWORD *outDataSize);
#ifdef __cplusplus
}
#endif //__cplusplus
typedef void (*FnDeleteDataATI)(void *pData);
typedef COMPRESSOR_ERROR (*FnCompressTextureATI)(DWORD width,
DWORD height,
UNCOMPRESSED_FORMAT sourceFormat,
COMPRESSED_FORMAT destinationFormat,
void *inputData,
void **dataOut,
DWORD *outDataSize);
extern void (*DeleteDataATI)(void *pData);
extern COMPRESSOR_ERROR (*CompressTextureATI)(DWORD width,
DWORD height,
UNCOMPRESSED_FORMAT sourceFormat,
COMPRESSED_FORMAT destinationFormat,
void *inputData,
void **dataOut,
DWORD *outDataSize);
#endif // _COMPRESSORLIB_H

15
RenderDll/Common/CRT.cpp Normal file
View File

@@ -0,0 +1,15 @@
#if defined(LINUX)
#include "platform.h"
#else
#include "Windows.h"
#endif
void CRTFreeData(void *pData)
{
free(pData);
}
void CRTDeleteArray(void *pData)
{
delete [] pData;
}

View File

@@ -0,0 +1,169 @@
/*=============================================================================
CommonRender.h: Crytek Common render helper functions and structures declarations.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#if !defined(COMMONRENDER_H__THIS_LINE_INSERTED_BY_VVP__15_10_1999__INCLUDED_)
#define COMMONRENDER_H__THIS_LINE_INSERTED_BY_VVP__15_10_1999__INCLUDED_
#include "Cry_Math.h"
#include "Defs.h"
#include "ColorDefs.h"
#include "Shaders/Shader.h"
//////////////////////////////////////////////////////////////////////
extern CRenderer *gRenDev;
extern bool g_bProfilerEnabled;
class CryModel;
// Cull functions
int gfCullBox(Vec3d& min, Vec3d& max);
bool gfCullPoint(Vec3d& org);
int gfCullSphere(Vec3d& cent, float radius);
int gfCullBoundBox(float *minmax);
//====================================================================
#define CR_LITTLE_ENDIAN
extern TArray <CFColor> gCurLightStyles;
struct SWaveForm;
struct SShader;
extern bool gbRgb;
_inline DWORD COLCONV (DWORD clr)
{
return ((clr & 0xff00ff00) | ((clr & 0xff0000)>>16) | ((clr & 0xff)<<16));
}
_inline void COLCONV (CFColor& col)
{
float v = col[0];
col[0] = col[2];
col[2] = v;
}
_inline void f2d(double *dst, float *src)
{
for (int i=0; i<16; i++)
{
dst[i] = src[i];
}
}
_inline void d2f(float *dst, double *src)
{
for (int i=0; i<16; i++)
{
dst[i] = (float)src[i];
}
}
//==============================================================================
#define SF_TRANS 4
//==============================================================================
struct SGenTC_NormalMap : public SGenTC
{
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_NormalMap);
return nSize;
}
};
struct SGenTC_ReflectionMap : public SGenTC
{
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_ReflectionMap);
return nSize;
}
};
struct SGenTC_SphereMap : public SGenTC
{
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_SphereMap);
return nSize;
}
};
struct SGenTC_EmbossMap : public SGenTC
{
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_EmbossMap);
return nSize;
}
};
struct SGenTC_ObjectLinear : public SGenTC
{
TArray<SParam> m_Params;
virtual ~SGenTC_ObjectLinear()
{
m_Params.Free();
}
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_ObjectLinear);
nSize += m_Params.GetSize() * sizeof(SParam);
return nSize;
}
};
struct SGenTC_EyeLinear : public SGenTC
{
TArray<SParam> m_Params;
virtual ~SGenTC_EyeLinear()
{
m_Params.Free();
}
virtual SGenTC *mfCopy();
virtual bool mfSet(bool bEnable);
virtual void mfCompile(char *params, SShader *ef);
virtual int Size()
{
int nSize = sizeof(SGenTC_EyeLinear);
nSize += m_Params.GetSize() * sizeof(SParam);
return nSize;
}
};
//=================================================================
#endif

149
RenderDll/Common/Defs.h Normal file
View File

@@ -0,0 +1,149 @@
#ifndef DEFS_H
#define DEFS_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef ABS
#define ABS(x) ((x)<0?-(x):(x))
#endif
#if !defined(SIGN) && !defined(DO_AMIGAOS)
#define SIGN(x) ((x)<0?-1:((x)>0?1:0))
#endif
#define EPSILON 0.001f /* Small value */
#define SMALL_EPSILON 0.000001f /* Very small value */
#ifndef OS_WIN32
//#define INFINITE 999999000 /* Very large number */
#endif
#ifndef PI
#define PI 3.14159265358979323f /* You know this number, don't you? */
#endif
#ifndef M_PI
#define M_PI PI
#endif
#undef DEBUG
#define DEBUG 1
#if !defined(LINUX)
#if defined(COMP_WCC)
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
#if defined(COMP_VC)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif
#endif//LINUX
# ifdef PROC_INTEL
// This is 'stolen' from someone (I don't remember who anymore). It
// is a nice and fast way to convert a floating point number to int
// (only works on a i386 type processor).
// It is equivalent to 'i=(int)(f+.5)'.
#define FIST_MAGIC ((float)((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0)))
_inline long QuickRound (float inval)
{
double dtemp = FIST_MAGIC + inval;
return ((*(long *)&dtemp) - 0x80000000);
}
_inline long QuickInt (float inval)
{
double dtemp = FIST_MAGIC + (inval-.4999f);
return ((*(long *)&dtemp) - 0x80000000);
}
// This is my own invention derived from the previous one. This converts
// a floating point number to a 16.16 fixed point integer. It is
// equivalent to 'i=(int)(f*65536.)'.
#define FIST_MAGIC2 ((float)((((65536.0 * 16)+(0.5))* 65536.0)))
inline long QuickInt16 (float inval)
{
double dtemp = FIST_MAGIC2 + inval;
return ((*(long *)&dtemp) - 0x80000000);
}
#endif //PROC_INTEL
#ifdef PROC_M68K
#define FIST_MAGIC ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0))
inline long QuickRound (float inval)
{
double dtemp = FIST_MAGIC + inval;
return (*(((long *)&dtemp) + 1)) - 0x80000000;
}
inline long QuickInt (float inval)
{
double dtemp = FIST_MAGIC + (inval-.4999);
return (*(((long *)&dtemp) + 1)) - 0x80000000;
}
#define FIST_MAGIC2 ((((65536.0 * 16)+(0.5))* 65536.0))
inline long QuickInt16 (float inval)
{
double dtemp = FIST_MAGIC2 + inval;
return (*(((long *)&dtemp) + 1)) - 0x80000000;
}
#endif
#if defined(PROC_INTEL) || defined(PROC_M68K)
# define QRound(x) QuickRound(x)
# define QInt(x) QuickInt(x)
# define QInt16(x) QuickInt16(x)
#else
# define QRound(x) ((int)((x)+.5))
# define QInt(x) ((int)(x))
# define QInt16(x) ((int)((x)*65536.))
#endif
// @@@ I don't know if there is a better way to convert
// a floating point to 8:24 fixed point (one with constants
// like the tricks above instead of the multiplication).
#define QInt24(x) (QInt16(((x)*256.0f)))
#if STATS
#define STAT(x) x
#else
#define STAT(x)
#endif
//#define SMALL_Z .01
#define SMALL_Z 0.1f
#define USE_OCCLUSION 0 // Experimental feature, will not work in this version.
// Some useful macros: these should be true at least for 32-bit processors
#define LONGFROM2SHORT(s1,s2) (((short)s1) << 16 | (((short)s2) & 0xffff))
#define SHORT1FROMLONG(l) (short)(((long)l) >> 16)
#define SHORT2FROMLONG(l) (short)(((long)l) & 0xffff)
#endif /*DEF_H*/

View File

@@ -0,0 +1,116 @@
/*=============================================================================
EvalFuncs.h : Funcs for evaluating shader parms.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#ifndef __EVALFUNCS_H__
#define __EVALFUNCS_H__
const int HALF_RAND = (RAND_MAX / 2);
_inline float RandomNum()
{
int rn;
rn = rand();
return ((float)(rn - HALF_RAND) / (float)HALF_RAND);
}
_inline float UnsRandomNum()
{
int rn;
rn = rand();
return ((float)rn / (float)RAND_MAX);
}
#define SHINE_TABLE_SIZE 16384
struct SEvalFuncs
{
static float EvalWaveForm(SWaveForm *wf);
static float EvalWaveForm(SWaveForm2 *wf);
static float EvalWaveForm2(SWaveForm *wf, float frac);
virtual void ETC_ShadowMap(int ns)=0;
virtual void ETC_Environment(int ns)=0;
virtual void ETC_Projection(int ns, float *Mat, float wdt, float hgt)=0;
virtual void ETC_SphereMap(int ns)=0;
virtual void ETC_SphereMapEnvironment(int ns)=0;
virtual void EALPHA_Object()=0;
virtual void EALPHA_OneMinusObject()=0;
virtual void EALPHA_Wave(SWaveForm *wf, UCol& color)=0;
virtual void EALPHA_Noise(SAlphaGenNoise *wf, UCol& color)=0;
virtual void EALPHA_Beam()=0;
virtual void ERGB_Object()=0;
virtual void ERGB_OneMinusObject()=0;
virtual void ERGB_Wave(SWaveForm *wf, UCol& col)=0;
virtual void ERGB_Noise(SRGBGenNoise *wf, UCol& col)=0;
virtual void EMOD_Deform(void)=0;
virtual void WaveDeform(SDeform *df)=0;
virtual void VerticalWaveDeform(SDeform *df)=0;
virtual void BulgeDeform(SDeform *df)=0;
virtual void SqueezeDeform(SDeform *df)=0;
virtual void FromCenterDeform(SDeform *df)=0;
virtual void FlareDeform(SDeform *df)=0;
virtual void BeamDeform(SDeform *df)=0;
};
// Shader evaluating functions for mergable geometry
// Software shader pipeline
struct SEvalFuncs_C : public SEvalFuncs
{
virtual void ETC_ShadowMap(int ns);
virtual void ETC_Environment(int ns);
virtual void ETC_Projection(int ns, float *Mat, float wdt, float hgt);
virtual void ETC_SphereMap(int ns);
virtual void ETC_SphereMapEnvironment(int ns);
virtual void EALPHA_Object();
virtual void EALPHA_OneMinusObject();
virtual void EALPHA_Wave(SWaveForm *wf, UCol& color);
virtual void EALPHA_Noise(SAlphaGenNoise *wf, UCol& color);
virtual void EALPHA_Beam() {};
virtual void ERGB_Object();
virtual void ERGB_OneMinusObject();
virtual void ERGB_Wave(SWaveForm *wf, UCol& col);
virtual void ERGB_Noise(SRGBGenNoise *wf, UCol& col);
virtual void EMOD_Deform(void);
virtual void WaveDeform(SDeform *df);
virtual void VerticalWaveDeform(SDeform *df);
virtual void BulgeDeform(SDeform *df);
virtual void SqueezeDeform(SDeform *df);
virtual void FromCenterDeform(SDeform *df);
virtual void FlareDeform(SDeform *df);
virtual void BeamDeform(SDeform *df);
};
// Shader evaluating functions for render elements
struct SEvalFuncs_RE : public SEvalFuncs_C
{
virtual void ETC_ShadowMap(int ns);
virtual void ETC_Environment(int ns);
virtual void ETC_Projection(int ns, float *Mat, float wdt, float hgt);
virtual void ETC_SphereMap(int ns);
virtual void ETC_SphereMapEnvironment(int ns);
virtual void EALPHA_Beam();
virtual void BeamDeform(SDeform *df);
virtual void WaveDeform(SDeform *df);
virtual void FlareDeform(SDeform *df);
virtual void VerticalWaveDeform(SDeform *df);
virtual void BulgeDeform(SDeform *df);
virtual void SqueezeDeform(SDeform *df);
};
//===================================================================================
#endif // __EVALFUNCS_H__

View File

@@ -0,0 +1,748 @@
/*=============================================================================
EvalFuncs_C : implementation of evaluator functions (Render Buffer data changing).
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define EVALFUNCS_C_CPP
#include "RenderPCH.h"
#include "shadow_renderer.h"
#include <IEntityRenderState.h>
//===========================================================================
//---------------------------------------------------------------------------
// Wave evaluator
float SEvalFuncs::EvalWaveForm(SWaveForm *wf)
{
int val;
float Amp;
float Freq;
float Phase;
float Level;
if (wf->m_Flags & WFF_LERP)
{
val = (int)(gRenDev->m_RP.m_RealTime * 597.0f);
val &= 0x3ff;
float fLerp = gRenDev->m_RP.m_tSinTable[val] * 0.5f + 0.5f;
if (wf->m_Amp != wf->m_Amp1)
Amp = LERP(wf->m_Amp, wf->m_Amp1, fLerp);
else
Amp = wf->m_Amp;
if (wf->m_Freq != wf->m_Freq1)
Freq = LERP(wf->m_Freq, wf->m_Freq1, fLerp);
else
Freq = wf->m_Freq;
if (wf->m_Phase != wf->m_Phase1)
Phase = LERP(wf->m_Phase, wf->m_Phase1, fLerp);
else
Phase = wf->m_Phase;
if (wf->m_Level != wf->m_Level1)
Level = LERP(wf->m_Level, wf->m_Level1, fLerp);
else
Level = wf->m_Level;
}
else
{
Level = wf->m_Level;
Amp = wf->m_Amp;
Phase = wf->m_Phase;
Freq = wf->m_Freq;
}
switch(wf->m_eWFType)
{
case eWF_None:
Warning( 0,0,"WARNING: SEvalFuncs::EvalWaveForm called with 'EWF_None' in Shader '%s'\n", gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
case eWF_Sin:
val = (int)((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
return Amp*gRenDev->m_RP.m_tSinTable[val&0x3ff]+Level;
case eWF_HalfSin:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
return Amp*gRenDev->m_RP.m_tHalfSinTable[val&0x3ff]+Level;
case eWF_InvHalfSin:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
return Amp*(1.0f-gRenDev->m_RP.m_tHalfSinTable[val&0x3ff])+Level;
case eWF_SawTooth:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*gRenDev->m_RP.m_tSawtoothTable[val]+Level;
case eWF_InvSawTooth:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*gRenDev->m_RP.m_tInvSawtoothTable[val]+Level;
case eWF_Square:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*gRenDev->m_RP.m_tSquareTable[val]+Level;
case eWF_Triangle:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*gRenDev->m_RP.m_tTriTable[val]+Level;
case eWF_Hill:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*gRenDev->m_RP.m_tHillTable[val]+Level;
case eWF_InvHill:
val = QRound((gRenDev->m_RP.m_RealTime*Freq+Phase)*1024.0f);
val &= 0x3ff;
return Amp*(1.0f-gRenDev->m_RP.m_tHillTable[val])+Level;
default:
Warning( 0,0,"WARNING: SEvalFuncs::EvalWaveForm: bad WaveType '%d' in Shader '%s'\n", wf->m_eWFType, gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
}
return 1;
}
float SEvalFuncs::EvalWaveForm(SWaveForm2 *wf)
{
int val;
switch(wf->m_eWFType)
{
case eWF_None:
Warning( 0,0,"WARNING: SEvalFuncs::EvalWaveForm called with 'EWF_None' in Shader '%s'\n", gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
case eWF_Sin:
val = FtoI((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
return wf->m_Amp*gRenDev->m_RP.m_tSinTable[val&0x3ff]+wf->m_Level;
case eWF_HalfSin:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
return wf->m_Amp*gRenDev->m_RP.m_tHalfSinTable[val&0x3ff]+wf->m_Level;
case eWF_InvHalfSin:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
return wf->m_Amp*(1.0f-gRenDev->m_RP.m_tHalfSinTable[val&0x3ff])+wf->m_Level;
case eWF_SawTooth:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tSawtoothTable[val]+wf->m_Level;
case eWF_InvSawTooth:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tInvSawtoothTable[val]+wf->m_Level;
case eWF_Square:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tSquareTable[val]+wf->m_Level;
case eWF_Triangle:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tTriTable[val]+wf->m_Level;
case eWF_Hill:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tHillTable[val]+wf->m_Level;
case eWF_InvHill:
val = QRound((gRenDev->m_RP.m_RealTime*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*(1.0f-gRenDev->m_RP.m_tHillTable[val])+wf->m_Level;
default:
Warning( 0,0,"WARNING: SEvalFuncs::EvalWaveForm: bad WaveType '%d' in Shader '%s'\n", wf->m_eWFType, gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
}
return 1;
}
float SEvalFuncs::EvalWaveForm2(SWaveForm *wf, float frac)
{
int val;
if (!(wf->m_Flags & WFF_CLAMP))
switch(wf->m_eWFType)
{
case eWF_None:
Warning( 0,0,"EvalWaveForm2 called with 'EWF_None' in Shader '%s'\n", gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
case eWF_Sin:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tSinTable[val]+wf->m_Level;
case eWF_SawTooth:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tSawtoothTable[val]+wf->m_Level;
case eWF_InvSawTooth:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tInvSawtoothTable[val]+wf->m_Level;
case eWF_Square:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tSquareTable[val]+wf->m_Level;
case eWF_Triangle:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tTriTable[val]+wf->m_Level;
case eWF_Hill:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*gRenDev->m_RP.m_tHillTable[val]+wf->m_Level;
case eWF_InvHill:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val &= 0x3ff;
return wf->m_Amp*(1-gRenDev->m_RP.m_tHillTable[val])+wf->m_Level;
default:
Warning( 0,0,"Warning: EvalWaveForm2: bad EWF '%d' in Shader '%s'\n", wf->m_eWFType, gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
}
else
switch(wf->m_eWFType)
{
case eWF_None:
Warning( 0,0,"Warning: EvalWaveForm2 called with 'EWF_None' in Shader '%s'\n", gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
case eWF_Sin:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tSinTable[val]+wf->m_Level;
case eWF_SawTooth:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tSawtoothTable[val]+wf->m_Level;
case eWF_InvSawTooth:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tInvSawtoothTable[val]+wf->m_Level;
case eWF_Square:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tSquareTable[val]+wf->m_Level;
case eWF_Triangle:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tTriTable[val]+wf->m_Level;
case eWF_Hill:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*gRenDev->m_RP.m_tHillTable[val]+wf->m_Level;
case eWF_InvHill:
val = QRound((frac*wf->m_Freq+wf->m_Phase)*1024.0f);
val = min(val, 1023);
return wf->m_Amp*(1.0f-gRenDev->m_RP.m_tHillTable[val])+wf->m_Level;
default:
Warning( 0,0,"Warning: EvalWaveForm2: bad EWF '%d' in Shader '%s'\n", wf->m_eWFType, gRenDev->m_RP.m_pShader->m_Name.c_str());
break;
}
return 1;
}
//=========================================================================================
//Calc Lights and generate per-vertex colors
void SEvalFuncs_C::ERGB_Object()
{
int i;
if (gRenDev->m_RP.m_pCurObject)
{
uint col = gRenDev->m_RP.m_pCurObject->m_Color.GetTrue();
col = COLCONV(col);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*(uint *)(ptr) = col;
}
}
}
void SEvalFuncs_C::ERGB_OneMinusObject()
{
int i;
if (gRenDev->m_RP.m_pCurObject)
{
uint col = !gRenDev->m_RP.m_pCurObject->m_Color.GetTrue();
col = COLCONV(col);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*(uint *)(ptr) = col;
}
}
}
void SEvalFuncs_C::EALPHA_Object()
{
int i;
byte a;
if (gRenDev->m_RP.m_pCurObject)
{
a = (byte)(gRenDev->m_RP.m_pCurObject->m_Color[3] * 255.0f);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD + 3;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
ptr[0] = a;
}
}
}
void SEvalFuncs_C::EALPHA_OneMinusObject()
{
int i;
byte a;
if (gRenDev->m_RP.m_pCurObject)
{
a = 255 - (byte)(gRenDev->m_RP.m_pCurObject->m_Color[3] * 255.0f);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD + 3;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
ptr[0] = a;
}
}
}
void SEvalFuncs_C::ERGB_Wave(SWaveForm *wf, UCol& col)
{
int i;
float val = EvalWaveForm(wf);
if (val < 0)
val = 0;
if (val > 1)
val = 1;
int v = (int)(val * 255.0f);
v = CLAMP(v, 0, 255);
col.bcolor[0] = col.bcolor[1] = col.bcolor[2] = v;
col.bcolor[3] = 255;
COLCONV(col.dcolor);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*(uint *)(ptr) = col.dcolor;
}
}
void SEvalFuncs_C::EALPHA_Wave(SWaveForm *wf, UCol& col)
{
int i;
float val = EvalWaveForm(wf);
int v = (int)(val * 255.0f);
v = CLAMP(v, 0, 255);
col.bcolor[3] = v;
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD + 3;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*ptr = v;
}
}
void SEvalFuncs_C::ERGB_Noise(SRGBGenNoise *wf, UCol& col)
{
int i;
float v = RandomNum();
byte r = (byte)(CLAMP(v * wf->m_RangeR + wf->m_ConstR, 0.0f, 1.0f) * 255.0f);
v = RandomNum();
byte g = (byte)(CLAMP(v * wf->m_RangeG + wf->m_ConstG, 0.0f, 1.0f) * 255.0f);
v = RandomNum();
byte b = (byte)(CLAMP(v * wf->m_RangeB + wf->m_ConstB, 0.0f, 1.0f) * 255.0f);
col.bcolor[0] = r;
col.bcolor[1] = g;
col.bcolor[2] = b;
COLCONV(col.dcolor);
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*(uint *)(ptr) = col.dcolor;
}
}
void SEvalFuncs_C::EALPHA_Noise(SAlphaGenNoise *wf, UCol& col)
{
int i;
float v = RandomNum();
byte a = (byte)(CLAMP(v * wf->m_RangeA + wf->m_ConstA, 0.0f, 1.0f) * 255.0f);
col.bcolor[3] = a;
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsD + 3;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride)
{
*ptr = a;
}
}
//=======================================================================
// RT Deformations
void SEvalFuncs_C::EMOD_Deform(void)
{
}
_inline void Deform(float val, Vec3d& vrt, byte *nrm)
{
float *vnrm = (float *)nrm;
vrt[0] += val * vnrm[0];
vrt[1] += val * vnrm[1];
vrt[2] += val * vnrm[2];
}
void SEvalFuncs_C::WaveDeform(SDeform *df)
{
int i, val;
float f;
gRenDev->m_RP.m_Flags |= RBF_MODIF_VERT;
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
byte *vnrm = ptr.PtrB+gRenDev->m_RP.m_OffsN;
float *WaveTable;
switch (df->m_DeformGen.m_eWFType)
{
case eWF_Sin:
default:
WaveTable = gRenDev->m_RP.m_tSinTable;
break;
case eWF_Triangle:
WaveTable = gRenDev->m_RP.m_tTriTable;
break;
case eWF_Square:
WaveTable = gRenDev->m_RP.m_tSquareTable;
break;
case eWF_SawTooth:
WaveTable = gRenDev->m_RP.m_tSawtoothTable;
break;
case eWF_InvSawTooth:
WaveTable = gRenDev->m_RP.m_tInvSawtoothTable;
break;
case eWF_Hill:
WaveTable = gRenDev->m_RP.m_tHillTable;
break;
}
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, vnrm+=gRenDev->m_RP.m_Stride)
{
f = ptr.VBPtr_0->x + ptr.VBPtr_0->y + ptr.VBPtr_0->z;
f = f*df->m_ScaleVerts + gRenDev->m_RP.m_RealTime*df->m_DeformGen.m_Freq + df->m_DeformGen.m_Phase;
f *= 1024.0;
val = QRound(f);
f = df->m_DeformGen.m_Amp * CRenderer::CV_r_wavescale * WaveTable[val&0x3ff] + df->m_DeformGen.m_Level;
Deform(f, *ptr.VBPtr_0, vnrm);
}
}
void SEvalFuncs_C::VerticalWaveDeform(SDeform *df)
{
}
void SEvalFuncs_C::FlareDeform(SDeform *df)
{
}
void SEvalFuncs_C::BeamDeform(SDeform *df)
{
}
void SEvalFuncs_C::SqueezeDeform(SDeform *df)
{
int i;
float f;
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
byte *nrm = ptr.PtrB+gRenDev->m_RP.m_OffsN;
gRenDev->m_RP.m_Flags |= RBF_MODIF_VERT;
f = EvalWaveForm(&df->m_DeformGen);
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, nrm+=gRenDev->m_RP.m_Stride)
{
float *vnrm = (float *)nrm;
ptr.VBPtr_0->x += f * vnrm[0];
ptr.VBPtr_0->y += f * vnrm[1];
ptr.VBPtr_0->z += f * vnrm[2];
}
}
void SEvalFuncs_C::BulgeDeform(SDeform *df)
{
int i;
float f;
int val;
Vec3d v;
gRenDev->m_RP.m_Flags |= RBF_MODIF_VERT;
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
byte *nrm = ptr.PtrB+gRenDev->m_RP.m_OffsN;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, nrm+=gRenDev->m_RP.m_Stride)
{
f = gRenDev->m_RP.m_pBaseTexCoordPointer[i].vert[0] + gRenDev->m_RP.m_pBaseTexCoordPointer[i].vert[1] + ptr.VBPtr_0->x + ptr.VBPtr_0->y + ptr.VBPtr_0->z;
f = f * df->m_ScaleVerts + df->m_DeformGen.m_Phase + gRenDev->m_RP.m_RealTime*df->m_DeformGen.m_Freq;
f *= 1024;
val = QRound(f);
val &= 0x3ff;
f = df->m_DeformGen.m_Amp * CRenderer::CV_r_wavescale * gRenDev->m_RP.m_tSinTable[val] + df->m_DeformGen.m_Level;
float *vnrm = (float *)nrm;
v[0] = f * vnrm[0];
v[1] = f * vnrm[1];
v[2] = f * vnrm[2];
*ptr.VBPtr_0 += v;
}
}
void SEvalFuncs_C::FromCenterDeform(SDeform *df)
{
if (!gRenDev->m_RP.m_pCurObject)
return;
gRenDev->m_RP.m_Flags |= RBF_MODIF_VERT;
int i;
float f;
Vec3d v;
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
Vec3d cent;
cent = gRenDev->m_RP.m_Center;
f = EvalWaveForm2(&df->m_DeformGen, gRenDev->m_RP.m_RealTime-gRenDev->m_RP.m_pCurObject->m_StartTime);
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
v = *ptr.VBPtr_0 - cent;
v.Normalize();
v *= f;
*ptr.VBPtr_0 += v;
}
}
//=================================================================
// Texture coords generate
void SEvalFuncs_C::ETC_Environment(int ns)
{
int i;
float f, d;
Vec3d v;
gRenDev->m_RP.m_Flags |= RBF_MODIF_TC;
UPipeVertex ptr = gRenDev->m_RP.m_Ptr;
byte *nrm = ptr.PtrB+gRenDev->m_RP.m_OffsN;
byte *tptr = gRenDev->m_RP.m_Ptr.PtrB + gRenDev->m_RP.m_OffsT + ns*16;
for (i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, tptr+=gRenDev->m_RP.m_Stride, nrm+=gRenDev->m_RP.m_Stride)
{
Vec3d *vnrm = (Vec3d *)nrm;
v = gRenDev->m_RP.m_ViewOrg - *ptr.VBPtr_0;
v.Normalize();
d = v | (*vnrm);
f = d * vnrm->y;
f += f;
*(float *)(tptr) = ((f - v[1]) + 1.0f) * 0.5f;
f = d * vnrm->z;
f += f;
*(float *)(tptr+4) = 0.5f - ((f - v[2]) * 0.5f);
}
}
void SEvalFuncs_C::ETC_Projection(int ns, float *Mat, float wdt, float hgt)
{
}
void SEvalFuncs_C::ETC_SphereMap(int ns)
{
int i;
CCObject *obj = gRenDev->m_RP.m_pCurObject;
gRenDev->m_RP.m_Flags |= RBF_MODIF_TC;
float r00 = gRenDev->m_ViewMatrix(0,0), r01 = gRenDev->m_ViewMatrix(0,1), r02 = gRenDev->m_ViewMatrix(0,2);
float r10 = gRenDev->m_ViewMatrix(1,0), r11 = gRenDev->m_ViewMatrix(1,1), r12 = gRenDev->m_ViewMatrix(1,2);
float r20 = gRenDev->m_ViewMatrix(2,0), r21 = gRenDev->m_ViewMatrix(2,1), r22 = gRenDev->m_ViewMatrix(2,2);
// Loop through the vertices, transforming each one and calculating
// the correct texture coordinates.
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB+gRenDev->m_RP.m_OffsT+ns*16;
byte *nrm = gRenDev->m_RP.m_Ptr.PtrB+gRenDev->m_RP.m_OffsN;
for( i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride, nrm+=gRenDev->m_RP.m_Stride )
{
Vec3d *vnrm = (Vec3d *)nrm;
float nx = vnrm->x;
float ny = vnrm->y;
float nz = vnrm->z;
// Check the z-component, to skip any vertices that face backwards
//if( nx*m13 + ny*m23 + nz*m33 > 0.0f )
// continue;
// Assign the spheremap's texture coordinates
*(float *)(ptr) = 0.5f * ( 1.0f + ( nx*r00 + ny*r10 + nz*r20 ) );
*(float *)(ptr+4) = 0.5f * ( 1.0f - ( nx*r01 + ny*r11 + nz*r21 ) );
}
}
void SEvalFuncs_C::ETC_SphereMapEnvironment(int ns)
{
int i;
CCObject *obj = gRenDev->m_RP.m_pCurObject;
gRenDev->m_RP.m_Flags |= RBF_MODIF_TC;
if (!obj)
return;
float r00 = obj->m_Matrix(0,0), r01 = obj->m_Matrix(0,1), r02 = obj->m_Matrix(0,2);
float r10 = obj->m_Matrix(1,0), r11 = obj->m_Matrix(1,1), r12 = obj->m_Matrix(1,2);
float r20 = obj->m_Matrix(2,0), r21 = obj->m_Matrix(2,1), r22 = obj->m_Matrix(2,2);
// Loop through the vertices, transforming each one and calculating
// the correct texture coordinates.
byte *ptr = gRenDev->m_RP.m_Ptr.PtrB+gRenDev->m_RP.m_OffsT+ns*16;
byte *nrm = gRenDev->m_RP.m_Ptr.PtrB+gRenDev->m_RP.m_OffsN;
for( i=0; i<gRenDev->m_RP.m_RendNumVerts; i++, ptr+=gRenDev->m_RP.m_Stride, nrm+=gRenDev->m_RP.m_Stride)
{
Vec3d *vnrm = (Vec3d *)nrm;
float nx = vnrm->x;
float ny = vnrm->y;
float nz = vnrm->z;
// Check the z-component, to skip any vertices that face backwards
//if( nx*m13 + ny*m23 + nz*m33 > 0.0f )
// continue;
// Assign the spheremap's texture coordinates
*(float *)(ptr) = 0.5f * ( 1.0f + ( nx*r00 + ny*r10 + nz*r20 ) );
*(float *)(ptr+4) = 0.5f * ( 1.0f + ( nx*r01 + ny*r11 + nz*r21 ) );
}
}
//========================================================================================
void SEvalFuncs_C::ETC_ShadowMap(int ns)
{
CRenderer *rd = gRenDev;
rd->m_RP.m_RECustomTexBind[ns] = -1;
assert(rd->m_RP.m_FlagsPerFlush & RBSI_SHADOWPASS);
int nsFrust;
if (rd->m_RP.m_pShader->m_eSort == eS_TerrainShadowPass)
nsFrust = 0;
else
nsFrust = ns + rd->m_RP.m_nCurStartCaster;
list2<ShadowMapLightSourceInstance> * lsources = (list2<ShadowMapLightSourceInstance>*)rd->m_RP.m_pCurObject->m_pShadowCasters;
// bool bActiveShadowReceiving = false;
// skip this stage if this entity was used to create this shadow map
if(!lsources || nsFrust>=lsources->Count())
{
if(!lsources)
Warning( 0,0,"Warning: SEvalFuncs_RE::ETC_ShadowMap: !lsources");
else
if(nsFrust<lsources->Count())
Warning( 0,0,"Warning: SEvalFuncs_RE::ETC_ShadowMap: nsFrust<lsources->Count()");
if ((rd->GetFeatures() & RFT_SHADOWMAP_SELFSHADOW) && !(rd->GetFeatures() & RFT_DEPTHMAPS))
rd->m_RP.m_RECustomTexBind[ns] = rd->m_TexMan->m_Text_Depth->m_Bind;
else
rd->m_RP.m_RECustomTexBind[ns] = rd->m_TexMan->m_Text_WhiteShadow->m_Bind;
if ((rd->GetFeatures() & RFT_SHADOWMAP_SELFSHADOW) && !(rd->GetFeatures() & RFT_DEPTHMAPS))
{
Matrix44 *mt = &rd->m_cEF.m_TempMatrices[ns][7];
mt->SetIdentity();
}
rd->SelectTMU(0);
return; // cancel this stage
}
if(!(*lsources)[nsFrust].m_pLS)
return;
// get projection frustum
ShadowMapFrustum * pShadowMapFrustum = (*lsources)[nsFrust].m_pLS->GetShadowMapFrustum(0);
// if(bActiveShadowReceiving)
// pShadowMapFrustum = (*lsources)[nsFrust].m_pLS->GetShadowMapFrustumPassiveCasters(0);
if(!pShadowMapFrustum)
return;
// detect usage of same lsource second time -> use penumbra frustum
if( nsFrust>0 && (*lsources)[nsFrust].m_pLS == (*lsources)[nsFrust-1].m_pLS && pShadowMapFrustum->pPenumbra)
pShadowMapFrustum = pShadowMapFrustum->pPenumbra;
Matrix44 *m = NULL;
Vec3d vObjTrans;
if (rd->m_RP.m_ObjFlags & FOB_TRANS_MASK)
{
m = &gRenDev->m_RP.m_pCurObject->m_Matrix;
vObjTrans = rd->m_RP.m_pCurObject->GetTranslation();
}
else
vObjTrans = Vec3(0,0,0);
// setup projection
gRenDev->SetupShadowOnlyPass(ns,
pShadowMapFrustum,
&((*lsources)[nsFrust].m_vProjTranslation),
(*lsources)[nsFrust].m_fProjScale,
vObjTrans,
1.f,
Vec3d(0,0,0),
m);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
// This is an inline file: it is meant to be included in multiple places
// to generate code out of the PROFILER macro.
// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
// This is the list of per-frame profilers used in the renderer system
// per-frame profilers: collect the infromation for each frame for
// displaying statistics at the beginning of each frame
PROFILER(Screen_Begin, "0Screen:Begin"); //
PROFILER(Screen_Update, "0Screen:Update"); //
PROFILER(State_Sorting, "0State:Sorting of RI"); //
PROFILER(State_SortingDist, "0State:Dist Sorting of RI"); //
PROFILER(State_LightStates, "0State:VLights"); //
PROFILER(State_RStates, "0State:RenderStates"); //
PROFILER(Draw_ObjSprites, "0Draw:ObjSprites"); //
PROFILER(Objects_Changes, "0O.Objects:Change"); //
PROFILER(Objects_ChangesSkinning, "1O.Objects:Skinning"); //
PROFILER(Objects_ObjInvTransform, "1O.Objects:InvTransform"); //
PROFILER(Texture_Changes, "0T0.Textures:Set"); //
PROFILER(Texture_ChangesUpload, "1T0.Textures:Stream (Immediat)"); //
PROFILER(Texture_Precache, "0Textures:PreloadPredict"); //
PROFILER(Texture_LoadFromCache, "0T1.Textures:LoadFromCache"); //
PROFILER(Texture_LoadFromCacheSync, "1T1.Textures:LoadFromCacheSync"); //
PROFILER(Texture_LoadFromCacheASync, "1T1.Textures:LoadFromCacheASync"); //
PROFILER(Texture_LoadFromCache_UploadSync, "1T1.Textures:UploadSync"); //
PROFILER(Texture_AsyncUpload, "0Textures:AsyncUpload"); //
PROFILER(Shader_PShaders, "0PS.Shader:PShaders"); //
PROFILER(Shader_PShaderActivate, "1PS.Shader:PShaderActivate"); //
PROFILER(Shader_PShadersParms, "1PS.Shader:PShaderParms"); //
PROFILER(Shader_VShaders, "0VS.Shader:VShaders"); //
PROFILER(Shader_VShaderActivate, "1VS.Shader:VShaderActivate"); //
PROFILER(Shader_VShadersParms, "1VS.Shader:VShaderParms"); //
PROFILER(Shader_VShadersMatr, "1VS.Shader:VShaderMatrices"); //
PROFILER(Mesh_CheckUpdate, "0CU.Mesh:CheckUpdate"); //
PROFILER(Mesh_CheckUpdateCreateGBuf, "1CU.Mesh:CreateGeneralBuf"); //
PROFILER(Mesh_CheckUpdateUpdateGBuf, "1CU.Mesh:UpdateGeneralBuf"); //
PROFILER(Mesh_CheckUpdateCreateSysTang, "1CU.Mesh:CreateSystemTangBuf"); //
PROFILER(Mesh_CheckUpdateCreateTBuf, "1CU.Mesh:CreateTangentBuf"); //
PROFILER(Mesh_CheckUpdateUpdateTBuf, "1CU.Mesh:UpdateTangentBuf"); //
PROFILER(Mesh_CheckUpdateCreateLMBuf, "1CU.Mesh:CreateLMBuf"); //
PROFILER(Mesh_CheckUpdateUpdateLMBuf, "1CU.Mesh:UpdateLMBuf"); //
PROFILER(Mesh_CheckUpdateUpdateInds, "1CU.Mesh:UpdateInds"); //
PROFILER(Mesh_CheckUpdateCallback, "1CU.Mesh:Callback"); //
PROFILER(Mesh_CheckUpdateRecreateSystem, "1CU.Mesh:CreateSystemBuffer"); //
PROFILER(Mesh_CheckUpdateSkinning, "1CU.Anim:Skinning"); //
PROFILER(Mesh_CreateVBuffers, "0Mesh:CreateVBuffer"); //
PROFILER(Mesh_CreateIBuffers, "0Mesh:CreateIBuffer"); //
PROFILER(Mesh_UpdateVBuffers, "0V.Mesh:UpdateVBuffer"); //
PROFILER(Mesh_UpdateVBuffersLock, "1V.Mesh:UpdateVBufferLock"); //
PROFILER(Mesh_UpdateVBuffersCopy, "1V.Mesh:UpdateVBufferCopy"); //
PROFILER(Mesh_UpdateVBuffersDynMerge, "1V.Mesh:UpdateVBufferDynMerge"); //
PROFILER(Mesh_UpdateIBuffers, "0I.Mesh:UpdateIBuffer"); //
PROFILER(Mesh_UpdateIBuffersLock, "1I.Mesh:UpdateIBufferLock"); //
PROFILER(Mesh_UpdateIBuffersCopy, "1I.Mesh:UpdateIBufferCopy"); //
PROFILER(Mesh_UpdateIBuffersDynMerge, "1I.Mesh:UpdateIBufferDynMerge"); //
PROFILER(Mesh_REPrepare, "0PRRE.Mesh:Preparing of RE"); //
PROFILER(Mesh_REPrepare_FlushOcleaf, "1PRRE.Mesh:Flush REOcleaf"); //
PROFILER(Mesh_REPrepare_Ocleaf, "1PRRE.Mesh:Prepare REOcleaf"); //
PROFILER(Mesh_REPrepare_Flush3DPoly, "1PRRE.Mesh:Flush 3DPoly"); //
PROFILER(Mesh_REPrepare_3DPoly, "1PRRE.Mesh:Prepare 3DPoly"); //
PROFILER(Draw_Predraw, "0Draw:Predraw"); //
PROFILER(Draw_IndexMesh, "0Draw:IndexedMesh"); //
PROFILER(Draw_EFIndexMesh, "0Draw:ShaderIndexedMesh"); //
PROFILER(Draw_2DImage, "0Draw:2DImage"); //
PROFILER(Prep_PrepareDepthMap, "0Prep:PrepareDepthMap");

272
RenderDll/Common/LZSS.H Normal file
View File

@@ -0,0 +1,272 @@
#define EXIT_SUCCESS 0
//#define EXIT_FAILURE 1
/**************************************************************
LZSS.C -- A Data Compression Program
(tab = 4 spaces)
***************************************************************
4/6/1989 Haruhiko Okumura
Use, distribute, and modify this program freely.
Please send me your improved versions.
PC-VAN SCIENCE
NIFTY-Serve PAF01022
CompuServe 74050,1022
**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 4096 /* size of ring buffer */
#define F 18 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length
if match_length is greater than this */
#define NIL N /* index for root of binary search trees */
unsigned long int
textsize = 0, /* text size counter */
codesize = 0, /* code size counter */
printcount = 0; /* counter for reporting progress every 1K bytes */
unsigned char
text_buf[N + F - 1]; /* ring buffer of size N,
with extra F-1 bytes to facilitate string comparison */
int match_position, match_length, /* of longest match. These are
set by the InsertNode() procedure. */
lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
parents -- These constitute binary search trees. */
FILE *infile, *outfile; /* input & output files */
void InitTree(void) /* initialize trees */
{
int i;
/* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
left children of node i. These nodes need not be initialized.
Also, dad[i] is the parent of node i. These are initialized to
NIL (= N), which stands for 'not used.'
For i = 0 to 255, rson[N + i + 1] is the root of the tree
for strings that begin with character i. These are initialized
to NIL. Note there are 256 trees. */
for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
for (i = 0; i < N; i++) dad[i] = NIL;
}
void InsertNode(int r)
/* Inserts string of length F, text_buf[r..r+F-1], into one of the
trees (text_buf[r]'th tree) and returns the longest-match position
and length via the global variables match_position and match_length.
If match_length = F, then removes the old node in favor of the new
one, because the old one will be deleted sooner.
Note r plays double role, as tree node and position in buffer. */
{
int i, p, cmp;
unsigned char *key;
cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
rson[r] = lson[r] = NIL; match_length = 0;
for ( ; ; ) {
if (cmp >= 0) {
if (rson[p] != NIL) p = rson[p];
else { rson[p] = r; dad[r] = p; return; }
} else {
if (lson[p] != NIL) p = lson[p];
else { lson[p] = r; dad[r] = p; return; }
}
for (i = 1; i < F; i++)
if ((cmp = key[i] - text_buf[p + i]) != 0) break;
if (i > match_length) {
match_position = p;
if ((match_length = i) >= F) break;
}
}
dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
dad[lson[p]] = r; dad[rson[p]] = r;
if (rson[dad[p]] == p) rson[dad[p]] = r;
else lson[dad[p]] = r;
dad[p] = NIL; /* remove p */
}
void DeleteNode(int p) /* deletes node p from tree */
{
int q;
if (dad[p] == NIL) return; /* not in tree */
if (rson[p] == NIL) q = lson[p];
else if (lson[p] == NIL) q = rson[p];
else {
q = lson[p];
if (rson[q] != NIL) {
do { q = rson[q]; } while (rson[q] != NIL);
rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
lson[q] = lson[p]; dad[lson[p]] = q;
}
rson[q] = rson[p]; dad[rson[p]] = q;
}
dad[q] = dad[p];
if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
dad[p] = NIL;
}
unsigned char *getcmP;
unsigned char *putcmP;
int Size,Count;
_inline int getcm()
{
if (Count++>=Size) return EOF;
return (int)*getcmP++;
};
_inline void putcm(int c)
{
*putcmP++=(unsigned char)c;
};
void Encode(void)
{
int i, c, len, r, s, last_match_length, code_buf_ptr;
unsigned char code_buf[17], mask;
codesize=0;
InitTree(); /* initialize trees */
code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
code_buf[0] works as eight flags, "1" representing that the unit
is an unencoded letter (1 byte), "0" a position-and-length pair
(2 bytes). Thus, eight units require at most 16 bytes of code. */
code_buf_ptr = mask = 1;
s = 0; r = N - F;
for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
any character that will appear often. */
for (len = 0; len < F && (c = getcm()) != EOF; len++)
text_buf[r + len] = c; /* Read F bytes into the last F bytes of
the buffer */
if ((textsize = len) == 0) return; /* text of size zero */
for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
each of which begins with one or more 'space' characters. Note
the order in which these strings are inserted. This way,
degenerate trees will be less likely to occur. */
InsertNode(r); /* Finally, insert the whole string just read. The
global variables match_length and match_position are set. */
do {
if (match_length > len) match_length = len; /* match_length
may be spuriously long near the end of text. */
if (match_length <= THRESHOLD) {
match_length = 1; /* Not long enough match. Send one byte. */
code_buf[0] |= mask; /* 'send one byte' flag */
code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */
} else {
code_buf[code_buf_ptr++] = (unsigned char) match_position;
code_buf[code_buf_ptr++] = (unsigned char)
(((match_position >> 4) & 0xf0)
| (match_length - (THRESHOLD + 1))); /* Send position and
length pair. Note match_length > THRESHOLD. */
}
if ((mask <<= 1) == 0) { /* Shift mask left one bit. */
for (i = 0; i < code_buf_ptr; i++) /* Send at most 8 units of */
putcm(code_buf[i]); /* code together */
codesize += code_buf_ptr;
code_buf[0] = 0; code_buf_ptr = mask = 1;
}
last_match_length = match_length;
for (i = 0; i < last_match_length &&
(c = getcm()) != EOF; i++) {
DeleteNode(s); /* Delete old strings and */
text_buf[s] = c; /* read new bytes */
if (s < F - 1) text_buf[s + N] = c; /* If the position is
near the end of buffer, extend the buffer to make
string comparison easier. */
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
/* Since this is a ring buffer, increment the position
modulo N. */
InsertNode(r); /* Register the string in text_buf[r..r+F-1] */
}
///
textsize += i;
//if ((textsize += i) > printcount) {
// printf("%12ld\r", textsize); printcount += 1024;
// /* Reports progress each time the textsize exceeds
// multiples of 1024. */
//}
////////
while (i++ < last_match_length) { /* After the end of text, */
DeleteNode(s); /* no need to read, but */
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
if (--len) InsertNode(r); /* buffer may not be empty. */
}
} while (len > 0); /* until length of string to be processed is zero */
if (code_buf_ptr > 1) { /* Send remaining code. */
for (i = 0; i < code_buf_ptr; i++) putcm(code_buf[i]);
codesize += code_buf_ptr;
}
// printf("In : %ld bytes\n", textsize); /* Encoding is done. */
// printf("Out: %ld bytes\n", codesize);
// printf("Out/In: %.3f\n", (double)codesize / textsize);
}
int Encodem(unsigned char *InBuf,unsigned char *OutBuf,int ASize)
{
getcmP=InBuf;
putcmP=OutBuf;
Size=ASize;
Count=0;
Encode();
return codesize;
}
void Decode(void) /* Just the reverse of Encode(). */
{
int i, j, k, r, c;
unsigned int flags;
for (i = 0; i < N - F; i++) text_buf[i] = ' ';
r = N - F; flags = 0;
for ( ; ; ) {
if (((flags >>= 1) & 256) == 0) {
if ((c = getcm()) == EOF) break;
flags = c | 0xff00; /* uses higher byte cleverly */
} /* to count eight */
if (flags & 1) {
if ((c = getcm()) == EOF) break;
putcm(c); text_buf[r++] = c; r &= (N - 1);
} else {
if ((i = getcm()) == EOF) break;
if ((j = getcm()) == EOF) break;
i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
for (k = 0; k <= j; k++) {
c = text_buf[(i + k) & (N - 1)];
putcm(c); text_buf[r++] = c; r &= (N - 1);
}
}
}
}
void Decodem(unsigned char *InBuf,unsigned char *OutBuf,int ASize)
{
getcmP=InBuf;
putcmP=OutBuf;
Size=ASize;
Count=0;
Decode();
}
/*
int main(int argc, char *argv[])
{
char *s;
if (argc != 4) {
printf("'lzss e file1 file2' encodes file1 into file2.\n"
"'lzss d file2 file1' decodes file2 into file1.\n");
return EXIT_FAILURE;
}
if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
|| (s = argv[2], (infile = fopen(s, "rb")) == NULL)
|| (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
printf("??? %s\n", s); return EXIT_FAILURE;
}
if (toupper(*argv[1]) == 'E') Encode(); else Decode();
fclose(infile); fclose(outfile);
return EXIT_SUCCESS;
}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,465 @@
#include "RenderPCH.h"
#include "i3dengine.h"
#include "cryheaders.h"
void CLeafBuffer::AddRE(CCObject *obj, IShader *ef, int nNumSort, IShader * pStateEff)
{
if(!m_NumIndices || !m_pMats->Count())
return;
int nGlobalShaderTemplateId = gRenDev->GetGlobalShaderTemplateId();
IShader *e;
SRenderShaderResources *sr;
for(int i=0; i<(*m_pMats).Count(); i++)
// if(!CRenderer::CV_r_draw_phys_only || ((*m_pMats)[i].m_Flags & MIF_PHYSIC))
{
if (!(*m_pMats)[i].pRE)
continue;
if (!ef)
e = (*m_pMats)[i].shaderItem.m_pShader;
else
e = ef;
sr = (*m_pMats)[i].shaderItem.m_pShaderResources;
if (e)
{
assert((*m_pMats)[i].pRE->m_pChunk->nFirstIndexId<60000);
if (e->GetREs()->Num())
gRenDev->EF_AddEf_NotVirtual(0, e->GetREs()->Get(0), e, sr, obj, nGlobalShaderTemplateId, pStateEff, nNumSort);
else
gRenDev->EF_AddEf_NotVirtual(0, (*m_pMats)[i].pRE, e, sr, obj, nGlobalShaderTemplateId, pStateEff, nNumSort);
}
}
}
void CLeafBuffer::UpdateCustomLighting(float fBackSideLevel, Vec3d vStatObjAmbientColor, const Vec3d & vLight, bool bCalcLighting)
{
bool bRGB = (gRenDev->GetFeatures() & RFT_RGBA) != 0;
vStatObjAmbientColor*=0.5f; // compensate overbrightness to make it work same as other objects
Vec3d vSunColor = iSystem->GetI3DEngine()->GetSunColor();
byte *pData = (byte *)m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData;
int nPosStride = m_VertexSize[m_pSecVertBuffer->m_vertexformat];
int nNormStride, nColorStride, nInfoStride;
bool * arrCullInfo = new bool[m_SecVertCount];
ushort *pInds = GetIndices(NULL);
bool bWasBark = false;
for(int i=0; i<(*m_pMats).Count(); i++)
{
if (!(*m_pMats)[i].pRE)
continue;
CMatInfo *mi = &(*m_pMats)[i];
IShader *ef = mi->shaderItem.m_pShader->GetTemplate(-1);
int nFl = ef->GetFlags3();
bool bTwoSided;
if (nFl & EF3_HASVCOLORS)
bTwoSided = (nFl & EF3_HASALPHATEST) != 0;
else
bTwoSided = (mi->shaderItem.m_pShaderResources->m_ResFlags & MTLFLAG_2SIDED)!=0;//ef && (ef->GetCull() == e CULL_None);
if (!bTwoSided)
bWasBark = true;
for (int j=mi->nFirstIndexId; j<mi->nNumIndices+mi->nFirstIndexId; j++)
{
int nIndex = pInds[j];
assert(nIndex>=0 && nIndex<m_SecVertCount);
arrCullInfo[nIndex] = bTwoSided;
}
}
if (bWasBark && CRenderer::CV_r_Vegetation_PerpixelLight && m_nVertexFormat != VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F)
ReCreateSystemBuffer(VERTEX_FORMAT_P3F_COL4UB_COL4UB_TEX2F);
// get offsets
byte *pPos = &pData[0];
byte *pNorm = GetNormalPtr(nNormStride);
uchar*pColor = GetColorPtr(nColorStride);
nInfoStride = sizeof(uint);
bool * pInfo = arrCullInfo;
int nTangStride, nBinormStride, nTNormStride, nSecColStride;
byte *pTang = GetTangentPtr(nTangStride);
byte *pBinorm = GetBinormalPtr(nBinormStride);
byte *pTNorm = GetTNormalPtr(nTNormStride);
byte *pSecCol = GetSecColorPtr(nSecColStride);
assert(pNorm && pPos && pColor);
assert(m_pMats);
float fAlpha = 1.0f; // m_pMats->Get(0)->fAlpha;
for(int i=0; i<m_SecVertCount; i++)
{
Vec3 & pos = *((Vec3*)pPos);
Vec3 & normal = *((Vec3*)pNorm);
bool bPerPixel = false;
if (!pInfo[0] && CRenderer::CV_r_Vegetation_PerpixelLight)
bPerPixel = true;
Vec3 vBr(1.f,1.f,1.f);
Vec3 vLightVec;
float fDot = 0;
if(bCalcLighting)
{
//IVO: normal is 0 in some cases!
//this is no solution, we have to fix it in the exporter
if (normal != Vec3(0.0f,0.0f,0.0f))
fDot = GetNormalized(normal).Dot(GetNormalized(vLight));
if(fDot<0)
{
if(pInfo[0])
fDot = -fDot; // double side lighting
else
fDot = 0;
}
if (!bPerPixel)
{
vBr.x = pInfo[0] ? ( vStatObjAmbientColor.x*2 + fDot*vSunColor.x*0.5f ) : ( vStatObjAmbientColor.x + fDot*vSunColor.x );
vBr.y = pInfo[0] ? ( vStatObjAmbientColor.y*2 + fDot*vSunColor.y*0.5f ) : ( vStatObjAmbientColor.y + fDot*vSunColor.y );
vBr.z = pInfo[0] ? ( vStatObjAmbientColor.z*2 + fDot*vSunColor.z*0.5f ) : ( vStatObjAmbientColor.z + fDot*vSunColor.z );
}
else
{
vBr = vStatObjAmbientColor;
vLightVec.x = vLight.Dot(*(Vec3 *)pTang);
vLightVec.y = vLight.Dot(*(Vec3 *)pBinorm);
vLightVec.z = vLight.Dot(*(Vec3 *)pTNorm);
vLightVec.Normalize();
//vLightVec = *(Vec3 *)pTang;
//vLightVec.Set(1,0,0);
if(bRGB)
{
pSecCol[0] = (uchar)((vLightVec.x+1.0f)*127.5f);
pSecCol[1] = (uchar)((vLightVec.y+1.0f)*127.5f);
pSecCol[2] = (uchar)((vLightVec.z+1.0f)*127.5f);
}
else
{
pSecCol[0] = (uchar)((vLightVec.z+1.0f)*127.5f);
pSecCol[1] = (uchar)((vLightVec.y+1.0f)*127.5f);
pSecCol[2] = (uchar)((vLightVec.x+1.0f)*127.5f);
}
}
if(fBackSideLevel<1.f)
{ // make back side darker
float fDot2 = Vec3(-pos.x,-pos.y,0).GetNormalized().Dot(Vec3d(vLight.x,vLight.y,vLight.z))*2;
if(fDot2<0)
fDot2=0;
vBr.x -= fDot2*(1.f-fBackSideLevel);
vBr.y -= fDot2*(1.f-fBackSideLevel);
vBr.z -= fDot2*(1.f-fBackSideLevel);
vBr.CheckMax(vStatObjAmbientColor);
}
}
Vec3d vColor; // take into account original vertex color
if(!CRenderer::CV_r_Vegetation_IgnoreVertColors && m_pLoadedColors)
{
vColor.x = m_pLoadedColors[i].x*vBr.x;
vColor.y = m_pLoadedColors[i].y*vBr.y;
vColor.z = m_pLoadedColors[i].z*vBr.z;
}
else
{
vColor = vBr*255.f;
}
vColor.CheckMin(Vec3d(255.f,255.f,255.f));
if(bRGB)
{
pColor[0] = uchar(vColor.x);
pColor[1] = uchar(vColor.y);
pColor[2] = uchar(vColor.z);
pColor[3] = uchar(fDot*255.0f);
}
else
{
pColor[0] = uchar(vColor.z);
pColor[1] = uchar(vColor.y);
pColor[2] = uchar(vColor.x);
pColor[3] = uchar(fDot*255.0f);
}
pPos += nPosStride;
pNorm += nNormStride;
pColor += nColorStride;
pSecCol += nSecColStride;
pTang += nTangStride;
pBinorm += nBinormStride;
pTNorm += nTNormStride;
pInfo ++;
}
if(m_pVertexBuffer)
gRenDev->ReleaseBuffer(m_pVertexBuffer);
delete [] arrCullInfo;
m_pVertexBuffer=0;
}
/*
void CLeafBuffer::UpdateColorInBufer(const Vec3d & vColor)
{
byte *pData = (byte *)m_pSecVertBuffer->m_data;
int nColorStride;
uchar*pColor = GetColorPtr(nColorStride);
for(int i=0; i<m_SecVertCount; i++)
{
pColor[0] = (uchar)(vColor[0]*255.0f);
pColor[1] = (uchar)(vColor[1]*255.0f);
pColor[2] = (uchar)(vColor[2]*255.0f);
pColor[3] = 255;
pColor += nColorStride;
}
if(m_pVertexBuffer)
gRenDev->ReleaseBuffer(m_pVertexBuffer);
m_pVertexBuffer=0;
}
*/
void CLeafBuffer::AddRenderElements(CCObject * pObj, int DLightMask, int nTemplate, int nFogVolumeID, int nSortId, IMatInfo * pIMatInfo)
{
if(!m_NumIndices || !m_pMats->Count())
return;
assert(m_pMats);
if(nTemplate<0)
{
int nGlobalShaderTemplateId = gRenDev->GetGlobalShaderTemplateId();
if(nGlobalShaderTemplateId>=0)
nTemplate = nGlobalShaderTemplateId;
}
for (int i=0; i<m_pMats->Count(); i++)
{
CMatInfo * pMat = m_pMats->Get(i);
// if(!pMat->nNumIndices) // stops rendering detail grass
// continue;
CREOcLeaf * pOrigRE = pMat->pRE;
// Override object material.
if (pIMatInfo)
{ // Assume that the root material is the first material, sub materials start from index 1.
if (i == 0)
pMat = (CMatInfo*)pIMatInfo;
else if (i-1 < pIMatInfo->GetSubMtlCount())
pMat = (CMatInfo*)pIMatInfo->GetSubMtl(i-1);
}
IShader * e = pMat->shaderItem.m_pShader;
SRenderShaderResources *sr = pMat->shaderItem.m_pShaderResources;
if (e && pOrigRE)// && pMat->nNumIndices)
{
TArray<CRendElement *> *pREs = e->GetREs();
if(nTemplate < EFT_USER_FIRST)
e->AddTemplate(sr, nTemplate);
assert(pOrigRE->m_pChunk->nFirstIndexId<60000);
if (pREs && pREs->Num())
gRenDev->EF_AddEf_NotVirtual(nFogVolumeID, pREs->Get(0), e, sr, pObj, nTemplate, 0, nSortId);
else
gRenDev->EF_AddEf_NotVirtual(nFogVolumeID, pOrigRE, e, sr, pObj, nTemplate, 0, nSortId);
if(m_nClientTextureBindID)
break;
}
} //i
}
/*
void CLeafBuffer::GenerateParticles(CCObject * pObj, ParticleParams * pParticleParams)
{
I3DEngine * pEng = (I3DEngine *)iSystem->GetIProcess();
// spawn particles
PipVertex * pDst = (PipVertex *)m_pSecVertBuffer->m_data;
for(int sn=0; sn<m_SecVertCount; sn++, pDst++)
{
for(int r=0; r<33 || r<99.f*rand()/RAND_MAX; r++)
sn++, pDst++;
if(sn<m_SecVertCount && pDst->nor.nz>0.5)
{
pParticleParams->vPosition.x = pDst->pos.x + pObj->m_Trans.x;
pParticleParams->vPosition.y = pDst->pos.y + pObj->m_Trans.y;
pParticleParams->vPosition.z = pDst->pos.z + pObj->m_Trans.z;
pEng->SpawnParticles( *pParticleParams );
}
}
}
*/
void CLeafBuffer::Render(const SRendParams & rParams, CCObject * pObj, TArray<int> & ShaderTemplates, int e_overlay_geometry, bool bNotCurArea, IMatInfo *pMaterial, bool bSupportDefaultShaderTemplates)
{
int nSortValue = (rParams.dwFObjFlags & FOB_NEAREST) ? eS_Nearest : rParams.nSortValue;
CCObject * pObjTransp = NULL;
for (int i=0; i<m_pMats->Count(); i++)
{
CMatInfo * pMat = m_pMats->Get(i);
CRendElement * pREOcLeaf = pMat->pRE;
// Override default material
if (pMaterial)
{
int nMatId = pMat->m_nCGFMaterialID;
if(nMatId<0)
continue;
// Assume that the root material is the first material, sub materials start from index 1.
if (nMatId == 0)
pMat = (CMatInfo*)pMaterial;
else if (nMatId-1 < pMaterial->GetSubMtlCount())
{
pMat = (CMatInfo*)pMaterial->GetSubMtl(nMatId-1);
}
}
SShader * pShader = (SShader *)pMat->shaderItem.m_pShader;
SRenderShaderResources* sr = pMat->shaderItem.m_pShaderResources;
if (pREOcLeaf && pShader)
{
int nTempl = rParams.nShaderTemplate;
if (bSupportDefaultShaderTemplates && nTempl == -2 && i<ShaderTemplates.Num())
nTempl = ShaderTemplates[i];
if (rParams.nShaderTemplate>0)
pShader->AddTemplate((SRenderShaderResources*)sr, (int&)rParams.nShaderTemplate,(const char *)NULL);
if(rParams.dwFObjFlags & FOB_FOGPASS)
if(pShader->mfGetTemplate(-1)->m_Flags & EF_OVERLAY)
continue; // skip overlays during fog pass - it will be fogged by base geometry fog pass
bool bTransparent =
(pObj->m_Color.a<1.f || !(pShader->mfGetTemplate(-1)->m_Flags2 & EF2_OPAQUE) || (sr && sr->m_Opacity != 1.0f));
IShader * pStateShader = rParams.pStateShader;
if(bTransparent)
{
if((rParams.dwFObjFlags & FOB_LIGHTPASS) || (rParams.dwFObjFlags & FOB_FOGPASS) || (nTempl == EFT_INVLIGHT))
continue;
if(nSortValue==eS_FogShader)
nSortValue=eS_FogShader_Trans;
if(!e_overlay_geometry)
{
if(pShader->mfGetTemplate(-1)->m_Flags & EF_OVERLAY)
continue;
}
else if(e_overlay_geometry >= 2 && pShader->mfGetTemplate(-1)->m_Flags & EF_OVERLAY)
{
if(bNotCurArea)
continue;
if(e_overlay_geometry == 2)
{
if(int(iTimer->GetCurrTime()*5)&1)
pStateShader = gRenDev->EF_LoadShader("NoZTestState", eSH_World, EF_SYSTEM );
}
else
pStateShader = gRenDev->EF_LoadShader("ZTestGreaterState", eSH_World, EF_SYSTEM );
}
if(!pObjTransp && pObj->m_DynLMMask != rParams.nStrongestDLightMask)
{ // make object for transparent geometry since it will use different light mask and
pObjTransp = gRenDev->EF_GetObject(true);
pObjTransp->CloneObject(pObj);
pObjTransp->m_DynLMMask = rParams.nStrongestDLightMask;
}
}
if( rParams.dwFObjFlags & FOB_RENDER_INTO_SHADOWMAP && (pMat->m_Flags & MIF_NOCASTSHADOWS) )
continue;
if( nSortValue == EFSLIST_STENCIL && bTransparent )
gRenDev->EF_AddEf_NotVirtual(rParams.nFogVolumeID, pREOcLeaf, pShader, sr,
(bTransparent&&pObjTransp) ? pObjTransp : pObj,
nTempl, pStateShader, 0);
else
gRenDev->EF_AddEf_NotVirtual(rParams.nFogVolumeID, pREOcLeaf, pShader, sr,
(bTransparent&&pObjTransp) ? pObjTransp : pObj,
nTempl, pStateShader, nSortValue);
}
} //i
}
void CLeafBuffer::RenderDebugLightPass(const Matrix44 & mat, int nLightMask, float fAlpha)
{
int nLightsNum = 0;
for(int i=0; i<32; i++)
if(nLightMask & (1<<i))
nLightsNum++;
CCObject * pObj = gRenDev->EF_GetObject(true);
pObj->m_Matrix = mat;
IShader * pShader = gRenDev->EF_LoadShader("ObjectColor_VP",eSH_World,EF_SYSTEM);
pObj->m_Color = CFColor(nLightsNum>=3,nLightsNum==2,nLightsNum==1,fAlpha);
for (int i=0; i<m_pMats->Count(); i++)
{
CRendElement * pREOcLeaf = m_pMats->Get(i)->pRE;
if (pREOcLeaf)
gRenDev->EF_AddEf_NotVirtual(0, pREOcLeaf, pShader, 0, pObj, 0);
}
}
/*
void CLeafBuffer::CopyVertices(byte * pVertsNew, int nVertFormatNew, int nNewVertsCount)
{
SBufInfoTable *pOffsNew = &gBufInfoTable[nVertFormatNew];
int nVertSizeNew = m_VertexSize[nVertFormatNew];
int nPosStride=0;
if(byte * pPosPtr = GetPosPtr(nPosStride))
for(int i=0; i<nNewVertsCount; i++)
*(DWORD*)&pPosPtr[i*nPosStride] = *(DWORD*)&pVertsNew[nVertSizeNew*i];
int nColorStride=0;
if(pOffsNew->OffsColor)
if(byte * pColorPtr = GetColorPtr(nColorStride))
for(int i=0; i<nNewVertsCount; i++)
*(DWORD*)&pColorPtr[i*nColorStride] = *(DWORD*)&pVertsNew[pOffsNew->OffsColor + nVertSizeNew*i];
int nSecColorStride=0;
if(pOffsNew->OffsSecColor)
if(byte * pSecColorPtr = GetSecColorPtr(nSecColorStride))
for(int i=0; i<nNewVertsCount; i++)
*(DWORD*)&pSecColorPtr[i*nSecColorStride] = *(DWORD*)&pVertsNew[pOffsNew->OffsSecColor + nVertSizeNew*i];
int nNormalStride=0;
if(pOffsNew->OffsNormal)
if(byte * pNormalPtr = GetNormalPtr(nNormalStride))
for(int i=0; i<nNewVertsCount; i++)
*(DWORD*)&pNormalPtr[i*nNormalStride] = *(DWORD*)&pVertsNew[pOffsNew->OffsNormal + nVertSizeNew*i];
int nTCStride=0;
if(pOffsNew->OffsTC)
if(byte * pTCPtr = GetUVPtr(nTCStride))
for(int i=0; i<nNewVertsCount; i++)
*(DWORD*)&pTCPtr[i*nTCStride] = *(DWORD*)&pVertsNew[pOffsNew->OffsTC + nVertSizeNew*i];
}
*/

View File

@@ -0,0 +1,417 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: LeafBufferSerialize.cpp
// Version: v1.00
// Created: 28/8/2001 by Vladimir Kajalin
// Compilers: Visual Studio.NET
// Description: LeafBuffer serialization
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "RenderPCH.h"
#include "cryheaders.h"
#include "nvtristrip/nvtristrip.h"
#include "serializebuffer.h"
#include "MakMatInfoFromMAT_ENTITY.h"
CryIRGB CF2IRGB(CFColor in)
{
CryIRGB out;
out.r = uchar(in.r*255);
out.g = uchar(in.g*255);
out.b = uchar(in.b*255);
return out;
}
char *SkipPath (char *pathname)
{
char *last;
last = pathname;
while (*pathname)
{
if (*pathname=='/' || *pathname=='\\')
last = pathname+1;
pathname++;
}
return last;
}
int CLeafBuffer__SetTexType(TextureMap3 *tm)
{
if (tm->type == TEXMAP_CUBIC)
return eTT_Cubemap;
else
if (tm->type == TEXMAP_AUTOCUBIC)
return eTT_AutoCubemap;
return eTT_Base;
}
bool CLeafBuffer::Serialize(int & nPos, uchar * pSerBuf, bool bSave, char * _szFolderName, char * _szFileName, double & dCIndexedMesh__LoadMaterial)
{ // Load
int i;
char szSignature[16]="";
if(!LoadBuffer(szSignature, 11, pSerBuf, nPos) || strcmp(szSignature,"LeafBuffer"))
return false;
LoadBuffer(&m_SecVertCount, sizeof(m_SecVertCount), pSerBuf, nPos);
if((*((int*)&pSerBuf[nPos])))
m_arrVertStripMap = new uint[(*((int*)&pSerBuf[nPos]))];
LoadBuffer( m_arrVertStripMap, m_SecVertCount*sizeof(m_arrVertStripMap[0]), pSerBuf, nPos);
m_SecIndices.LoadFromBuffer(pSerBuf, nPos);
m_NumIndices = m_SecIndices.Num();
if((*((int*)&pSerBuf[nPos])) && !m_pIndicesPreStrip)
m_pIndicesPreStrip = new list2<unsigned short>;
m_pIndicesPreStrip->LoadFromBuffer(pSerBuf, nPos);
LoadBuffer(&m_nPrimetiveType,sizeof(m_nPrimetiveType), pSerBuf, nPos);
if((*((int*)&pSerBuf[nPos])))
{
m_pLoadedColors = new Vec3d[(*((int*)&pSerBuf[nPos]))/sizeof(m_pLoadedColors[0])];
assert((*((int*)&pSerBuf[nPos]))/sizeof(m_pLoadedColors[0]) == m_SecVertCount);
}
LoadBuffer( m_pLoadedColors, m_SecVertCount*sizeof(m_pLoadedColors[0]), pSerBuf, nPos);
// load mat info
m_pMats = new list2<CMatInfo>;
m_bMaterialsWasCreatedInRenderer = true;
m_pMats->LoadFromBuffer(pSerBuf, nPos);
// create materaial
for (i=0; i<m_pMats->Count(); i++)
{
m_pMats->GetAt(i).pRE = 0;
MAT_ENTITY * pMatEnt = new MAT_ENTITY;
LoadBuffer(pMatEnt, sizeof(*pMatEnt), pSerBuf, nPos);
m_pMats->Get(i)->pMatEnt = pMatEnt;
// skip loading of fake mats
if(m_pMats->Get(i)->nNumIndices && m_pMats->Get(i)->nNumVerts)
if(_szFileName && _szFolderName)
{
AUTO_PROFILE_SECTION(iSystem->GetITimer(), dCIndexedMesh__LoadMaterial);
CIndexedMesh__LoadMaterial(_szFileName, _szFolderName, m_pMats->GetAt(i), gRenDev, pMatEnt);
}
delete m_pMats->Get(i)->pMatEnt;
m_pMats->Get(i)->pMatEnt=0;
if(m_pMats->GetAt(i).m_dwNumSections)
{
m_pMats->GetAt(i).m_pPrimitiveGroups = new SPrimitiveGroup[m_pMats->GetAt(i).m_dwNumSections];
LoadBuffer((void*)m_pMats->GetAt(i).m_pPrimitiveGroups,
sizeof(SPrimitiveGroup)*m_pMats->GetAt(i).m_dwNumSections, pSerBuf, nPos);
}
}
// make system vert buffer
m_pSecVertBuffer = new CVertexBuffer();
LoadBuffer( m_pSecVertBuffer, sizeof(CVertexBuffer), pSerBuf, nPos); // need to restore
// load positions
if(*((int*)&pSerBuf[nPos]))
{
assert(m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData); // should not be zero before saving
m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData = new uchar[m_SecVertCount*m_VertexSize[m_pSecVertBuffer->m_vertexformat]];
}
else
assert(!m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData);
assert(m_SecVertCount*m_VertexSize[m_pSecVertBuffer->m_vertexformat] == (*((int*)&pSerBuf[nPos])));
LoadBuffer( m_pSecVertBuffer->m_VS[VSF_GENERAL].m_VData, m_SecVertCount*m_VertexSize[m_pSecVertBuffer->m_vertexformat], pSerBuf, nPos);
// load tangents
if(*((int*)&pSerBuf[nPos]))
{
assert(m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData); // should not be zero before saving
m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData = new SPipTangents[m_SecVertCount];
}
else
assert(!m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData);
assert(m_SecVertCount*sizeof(SPipTangents) == (*((int*)&pSerBuf[nPos])));
LoadBuffer( m_pSecVertBuffer->m_VS[VSF_TANGENTS].m_VData, m_SecVertCount*sizeof(SPipTangents), pSerBuf, nPos);
assert(!m_pVertexBuffer); // not needed
LoadBuffer(&m_vBoxMax, sizeof(m_vBoxMax), pSerBuf, nPos);
LoadBuffer(&m_vBoxMin, sizeof(m_vBoxMin), pSerBuf, nPos);
int bHasVtxMap = 0;
LoadBuffer(&bHasVtxMap, sizeof(bHasVtxMap), pSerBuf,nPos);
if (bHasVtxMap)
{
m_arrVtxMap = new uint[m_SecVertCount];
LoadBuffer(m_arrVtxMap, sizeof(uint)*m_SecVertCount, pSerBuf,nPos);
}
// make REs
for (i=0; i<(*m_pMats).Count(); i++)
{
if(m_pMats->Get(i)->nNumIndices && m_pMats->Get(i)->nNumVerts)
{
CREOcLeaf *re = (CREOcLeaf *)gRenDev->EF_CreateRE(eDATA_OcLeaf);
re->m_pChunk = &(*m_pMats)[i];
re->m_pBuffer = this;
assert (re->m_pChunk->nNumIndices < 60000);
re->m_pChunk->pRE = re;
// set sort offset
// IShader * ef = m_pMats->Get(i)->shaderItem.m_pShader->GetTemplate(-1);
// bool bTwoSided = ef && (ef->GetCull() == eCULL_None);
bool bTwoSided = (m_pMats->Get(i)->shaderItem.m_pShaderResources->m_ResFlags & MTLFLAG_2SIDED)!=0;//ef && (ef->GetCull() == e CULL_None);
re->m_SortId = i + 2*(!bTwoSided); // render double sided leafs last
}
else
(*m_pMats)[i].pRE = 0;
}
return 0;
}
bool CLeafBuffer::LoadMaterial(int m,
const char *szFileName, const char *szFolderName,
list2<CMatInfo> & lstMatTable, IRenderer * pRenderer,
MAT_ENTITY * me, bool bFake)
{
if(m<0 || bFake)//!pCGF->m_lstMaterials[m].IsStdMat)
{
CMatInfo fake;
lstMatTable.Add(fake);
return false;
}
// assert(strlen(szFolderName)+strlen(pCGF->m_lstMaterials[m].map_d.name)<1024);
// m_pSystem->GetIConsole()->Exit("LoadCGF: texture path len error");
SInputShaderResources Res;
memset(&Res, 0, sizeof(Res));
SLightMaterial LMs;
// MAT_ENTITY *me = &pCGF->m_lstMaterials[m];
if (me->m_New && (me->col_d.r>5 || me->col_d.g>5 || me->col_d.b>5 || me->col_s.r>5 || me->col_s.g>5 || me->col_s.b>5))
{
Res.m_LMaterial = &LMs;
Res.m_LMaterial->Front.m_Ambient = CFColor(me->col_a.r/255.f,me->col_a.g/255.f,me->col_a.b/255.f);
Res.m_LMaterial->Front.m_Diffuse = CFColor(me->col_d.r/255.f,me->col_d.g/255.f,me->col_d.b/255.f);
Res.m_LMaterial->Front.m_Specular = CFColor(me->col_s.r/255.f,me->col_s.g/255.f,me->col_s.b/255.f);
Res.m_LMaterial->Front.m_Specular *= me->specLevel;
Res.m_LMaterial->Front.m_Specular.Clamp();
Res.m_LMaterial->Front.m_Emission = Res.m_LMaterial->Front.m_Diffuse * me->selfIllum;
Res.m_LMaterial->Front.m_SpecShininess = me->specShininess;
}
char diffuse[256]="";
strcpy(diffuse, me->map_d.name);
char bump[256]="";
strcpy(bump, me->map_b.name);
char normalmap[256]="";
if(me->map_displ.name[0] && (me->flags & MTLFLAG_CRYSHADER))
strcpy(normalmap, me->map_displ.name);
char opacity[256]="";
char decal[256]="";
if(me->map_o.name[0])
{
if (me->flags & MTLFLAG_CRYSHADER)
strcpy(decal, me->map_o.name);
else
strcpy(opacity, me->map_o.name);
}
char gloss[256]="";
if(me->map_g.name[0])
strcpy(gloss, me->map_g.name);
char cubemap[256]="";
char env[256]="";
if(me->map_e.name[0])
strcpy(env, me->map_e.name);
char spec[256]="";
if(me->map_s.name[0])
strcpy(spec, me->map_s.name);
char det[256]="";
if(me->map_detail.name[0])
strcpy(det, me->map_detail.name);
char subsurf[256]="";
if(me->map_subsurf.name[0])
strcpy(subsurf, me->map_subsurf.name);
char refl[256]="";
if(me->map_e.name[0])
strcpy(refl, me->map_e.name);
char * mat_name = me->name;
// fill MatInfo struct
CMatInfo & newMat = lstMatTable[m];
// strcpy(newMat.szDiffuse, diffuse);
if (me->Dyn_Bounce == 1.0f)
newMat.m_Flags |= MIF_PHYSIC;
if (me->Dyn_StaticFriction == 1.0f)
newMat.m_Flags |= MIF_NOCASTSHADOWS;
/* if (nLM > 0)
{
Res.m_Textures[EFTT_LIGHTMAP].m_TU.m_ITexPic = m_pSystem->GetIRenderer()->EF_GetTextureByID(nLM);
Res.m_Textures[EFTT_LIGHTMAP].m_Name = Res.m_Textures[EFTT_LIGHTMAP].m_TU.m_ITexPic->GetName();
}
if (nLM_LD > 0)
{
Res.m_Textures[EFTT_LIGHTMAP_DIR].m_TU.m_ITexPic = m_pSystem->GetIRenderer()->EF_GetTextureByID(nLM_LD);
Res.m_Textures[EFTT_LIGHTMAP_DIR].m_Name = Res.m_Textures[EFTT_LIGHTMAP].m_TU.m_ITexPic->GetName();
}*/
Res.m_TexturePath = szFolderName;
Res.m_Textures[EFTT_DIFFUSE].m_Name = diffuse;
Res.m_Textures[EFTT_GLOSS].m_Name = gloss;
Res.m_Textures[EFTT_SUBSURFACE].m_Name = subsurf;
Res.m_Textures[EFTT_BUMP].m_Name = bump;
Res.m_Textures[EFTT_NORMALMAP].m_Name = normalmap;
Res.m_Textures[EFTT_CUBEMAP].m_Name = cubemap[0] ? cubemap : env;
Res.m_Textures[EFTT_SPECULAR].m_Name = spec;
Res.m_Textures[EFTT_DETAIL_OVERLAY].m_Name = det;
Res.m_Textures[EFTT_OPACITY].m_Name = opacity;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_Name = decal;
Res.m_Textures[EFTT_SUBSURFACE].m_Name = subsurf;
Res.m_Textures[EFTT_REFLECTION].m_Name = refl;
Res.m_Textures[EFTT_REFLECTION].m_TU.m_eTexType = (ETexType)SetTexType(&me->map_e);
Res.m_Textures[EFTT_CUBEMAP].m_TU.m_eTexType = (ETexType)SetTexType(&me->map_e);
Res.m_Textures[EFTT_SUBSURFACE].m_TU.m_eTexType = (ETexType)SetTexType(&me->map_subsurf);
Res.m_Textures[EFTT_BUMP].m_TU.m_eTexType = eTT_Bumpmap;
Res.m_ResFlags = me->flags;
Res.m_Opacity = me->opacity;
Res.m_AlphaRef = me->Dyn_SlidingFriction;
if (me->flags & MTLFLAG_CRYSHADER)
Res.m_AlphaRef = me->alpharef;
if (decal[0])
Res.m_Textures[EFTT_DECAL_OVERLAY].m_Amount = me->map_o.Amount;
Res.m_Textures[EFTT_DIFFUSE].m_Amount = me->map_d.Amount;
Res.m_Textures[EFTT_BUMP].m_Amount = me->map_b.Amount;
if (me->flags & MTLFLAG_CRYSHADER)
Res.m_Textures[EFTT_NORMALMAP].m_Amount = me->map_displ.Amount;
Res.m_Textures[EFTT_OPACITY].m_Amount = me->map_o.Amount;
Res.m_Textures[EFTT_REFLECTION].m_Amount = me->map_e.Amount;
Res.m_Textures[EFTT_SUBSURFACE].m_Amount = me->map_subsurf.Amount;
Res.m_Textures[EFTT_DIFFUSE].m_TexFlags = me->map_d.flags;
//Res.m_Textures[EFTT_SUBSURFACE].m_TexFlags = me->map_d.flags;
Res.m_Textures[EFTT_GLOSS].m_TexFlags = me->map_g.flags;
Res.m_Textures[EFTT_BUMP].m_TexFlags = me->map_b.flags;
Res.m_Textures[EFTT_CUBEMAP].m_TexFlags = me->map_e.flags;
Res.m_Textures[EFTT_SPECULAR].m_TexFlags = me->map_s.flags;
Res.m_Textures[EFTT_DETAIL_OVERLAY].m_TexFlags = me->map_detail.flags;
Res.m_Textures[EFTT_SUBSURFACE].m_TexFlags = me->map_subsurf.flags;
if (!Res.m_Textures[EFTT_DETAIL_OVERLAY].m_Name.empty())
{
Res.m_Textures[EFTT_DETAIL_OVERLAY].m_TexModificator.m_Tiling[0] = me->map_detail.uscl_val;
Res.m_Textures[EFTT_DETAIL_OVERLAY].m_TexModificator.m_Tiling[1] = me->map_detail.vscl_val;
}
if (!Res.m_Textures[EFTT_OPACITY].m_Name.empty())
{
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Tiling[0] = me->map_o.uscl_val;
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Tiling[1] = me->map_o.vscl_val;
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Rot[0] = Degr2Word(me->map_o.urot_val);
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Rot[1] = Degr2Word(me->map_o.vrot_val);
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Offs[0] = me->map_o.uoff_val;
Res.m_Textures[EFTT_OPACITY].m_TexModificator.m_Offs[1] = me->map_o.voff_val;
Res.m_Textures[EFTT_OPACITY].m_bUTile = me->map_o.utile;
Res.m_Textures[EFTT_OPACITY].m_bVTile = me->map_o.vtile;
}
if (!Res.m_Textures[EFTT_DECAL_OVERLAY].m_Name.empty())
{
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Tiling[0] = me->map_o.uscl_val;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Tiling[1] = me->map_o.vscl_val;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Rot[0] = Degr2Word(me->map_o.urot_val);
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Rot[1] = Degr2Word(me->map_o.vrot_val);
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Offs[0] = me->map_o.uoff_val;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_TexModificator.m_Offs[1] = me->map_o.voff_val;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_bUTile = me->map_o.utile;
Res.m_Textures[EFTT_DECAL_OVERLAY].m_bVTile = me->map_o.vtile;
}
char mName[128];
strcpy(mName, mat_name);
char *str = strchr(mat_name, '/');
if (str)
{
mName[str-mat_name] = 0;
strncpy(newMat.sScriptMaterial, &str[1], sizeof(newMat.sScriptMaterial));
newMat.sScriptMaterial[sizeof(newMat.sScriptMaterial)-1]=0;
}
else
{
newMat.sScriptMaterial[0] = 0;
}
char *templName = NULL;;
if(strnicmp(mName, "$s_",3)==0)
{
templName = &mName[3];
}
else
if(str=strchr(mName, '('))
{
mName[str-mName] = 0;
templName = &mName[str-mName+1];
if(str=strchr(templName, ')'))
templName[str-templName] = 0;
}
uchar nInvert = 0;
if (templName && templName[0] == '#')
{
templName++;
nInvert = 1;
}
// strcpy(newMat.szMatName, mName);
// load shader
if(mName[0]==0)
strcpy(mName,"nodraw");
newMat.shaderItem = pRenderer->EF_LoadShaderItem(mName, eSH_World, true, templName, 0, &Res);
//newMat.shaderItem->m_pShader->AdjustResources(newMat.shaderItem->m_pShaderResources);
//IShader * ef = newMat.shaderItem.m_pShader->GetTemplate(-1);
//if(ef->GetPhysMaterialFlags() & MATF_NOCLIP)
// newMat.m_Flags &= ~MIF_PHYSIC;
// strcpy(newMat.szFolderName, szFolderName);
// remember polybump state
newMat.m_Flags &= ~MIF_POLYBUMP;
// pFace->shader_id = m_lstMatTable.Count();
newMat.fAlpha = me->opacity;
return true;
}
int CLeafBuffer::SetTexType(TextureMap3 *tm)
{
if (tm->type == TEXMAP_CUBIC)
return eTT_Cubemap;
else
if (tm->type == TEXMAP_AUTOCUBIC)
return eTT_AutoCubemap;
return eTT_Base;
}

View File

@@ -0,0 +1,164 @@
/*=============================================================================
LightMaterial.cpp : implementation of LightMaterial interface.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#define LIGHTMATERIAL_CPP
#include "RenderPCH.h"
#include "CommonRender.h"
SLightMaterial* SLightMaterial::current_material = 0;
int SLightMaterial::m_ObjFrame = 0;
TArray<SLightMaterial *> SLightMaterial::known_materials;
void SLightMaterial::Release()
{
m_nRefCounter--;
if (!m_nRefCounter)
{
SLightMaterial::known_materials[Id] = NULL;
delete this;
}
}
void SLightMaterial::mfApply(int Flags)
{
if (current_material == this && gRenDev->m_RP.m_FrameObject == m_ObjFrame && gRenDev->m_RP.m_CurrentVLightFlags == Flags)
return;
gRenDev->m_RP.m_CurrentVLights = 0;
gRenDev->m_RP.m_CurrentVLightFlags = Flags;
//if (!CRenderer::CV_r_hwlights)
// return;
if (Flags & LMF_DISABLE)
return;
m_ObjFrame = gRenDev->m_RP.m_FrameObject;
current_material = this;
if (Flags & LMF_BUMPMATERIAL)
gRenDev->m_RP.m_pCurLightMaterial = this;
else
gRenDev->EF_LightMaterial(this, Flags);
}
SLightMaterial *SLightMaterial::mfAdd(char *name, SLightMaterial *Compare)
{
int i;
SLightMaterial* mat;
if (Compare)
{
for (i=0; i<known_materials.Num(); i++)
{
mat = known_materials[i];
if (!mat)
continue;
if (mat->Front == Compare->Front)
{
mat->m_nRefCounter++;
return mat;
}
}
char name[128];
int n = 0;
int nFirstUse = -1;
while (true)
{
sprintf(name, "$Auto_%d", n);
for (i=0; i<known_materials.Num(); i++)
{
mat = known_materials[i];
if (!mat)
{
if (nFirstUse < 0)
nFirstUse = i;
continue;
}
if (!strcmp(mat->name, name))
break;
}
if (i == known_materials.Num())
{
SLightMaterial *mt = new SLightMaterial;
mt->m_nRefCounter = 1;
if (nFirstUse >= 0)
i = nFirstUse;
else
known_materials.AddIndex(1);
mt->Id = i;
known_materials[i] = mt;
strcpy (mt->name, name);
mt->Front = Compare->Front;
mt->side = FRONT;
return known_materials[i];
}
n++;
}
}
if (!name || !name[0])
iConsole->Exit("SLightMaterial::mfAdd: NULL name\n");
//
// search the currently loaded materials
//
for (i=0; i<known_materials.Num(); i++)
{
mat = known_materials[i];
if (!stricmp (mat->name, name) )
{
//ShPrintf(MSG_WARNING, "LightMaterial '%s' is duplicated\n", name);
mat->m_nRefCounter++;
return mat;
}
}
SLightMaterial *mt = new SLightMaterial;
mt->m_nRefCounter = 1;
known_materials.AddIndex(1);
strcpy (mt->name, name);
mt->Id = i;
known_materials[i] = mt;
return known_materials[i];
}
SLightMaterial *SLightMaterial::mfGet(char *name)
{
int i;
SLightMaterial* mat;
if (!name || !name[0])
iConsole->Exit ("SLightMaterial::mfGet: NULL name\n");
//
// search the currently loaded materials
//
for (i=0; i<known_materials.Num(); i++)
{
mat = known_materials[i];
if (!stricmp (mat->name, name) )
{
return mat;
}
}
Warning( 0,0,"Couldn't find LightMaterial '%s' (use <Default>\n", name);
if (known_materials.Num())
return known_materials[0];
return NULL;
}

250
RenderDll/Common/Names.cpp Normal file
View File

@@ -0,0 +1,250 @@
/*=============================================================================
Names.cpp : implementation of the CName class using hash tables.
Copyright 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "Names.int"
TArray<SNameEntry *> CName::mNames;
TArray<int> CName::mAvailable;
SNameEntry* CName::mNameHash[8192];
int CName::mDuplicate;
int CName::Size()
{
INT_PTR nSize = 0; //AMD Port
nSize += mAvailable.GetMemoryUsage();
for (int i=0; i<mNames.GetSize(); i++)
{
if (i < mNames.Num())
{
nSize += 4;
if (mNames[i])
nSize += mNames[i]->Size();
}
else
nSize += 4;
}
nSize += sizeof(long) * 256;
return nSize;
}
//===================================================================
SNameEntry* CreateNewNameEntry(const char *str, int num, int m, SNameEntry *sFNE)
{
SNameEntry *lsFNE;
lsFNE = (SNameEntry *)malloc( strlen(str)+sizeof(SNameEntry)-MAX_SNAME_LEN+1);
lsFNE->mNumName = num;
lsFNE->mFlags = m;
lsFNE->mNext = sFNE;
strcpy(lsFNE->mName, str);
return lsFNE;
}
void DestroyNameEntry(SNameEntry* sFNE)
{
free(sFNE);
}
CName::CName(const char* str, EFindName efn)
{
char tstr[MAX_SNAME_LEN];
SNameEntry * sFNE;
assert( str );
if ( !mNames.Num() )
mfInitTables();
if ( *str == 0 )
mNameIndex = 0;
strncpy(tstr, str, MAX_SNAME_LEN);
int i = 0;
long hash = mfGetHash(tstr);
sFNE = mNameHash[hash];
while ( sFNE )
{
if ( !stricmp(tstr,sFNE->mName) )
{
mNameIndex = sFNE->mNumName;
return;
}
sFNE = sFNE->mNext;
}
if ( efn == eFN_Find )
mNameIndex = 0;
else
{
if ( mAvailable.Num() )
{
mNameIndex = mAvailable[mAvailable.Num()-1];
mAvailable._Remove(mAvailable.Num()-1, 1);
}
else
{
i = mNames.Num();
mNames.AddIndex(1);
mNameIndex = i;
}
sFNE = CreateNewNameEntry(str, mNameIndex, 0, mNameHash[hash] );
mNameHash[hash] = sFNE;
mNames[mNameIndex] = sFNE;
if ( efn == eFN_Intrinsic )
mNames[mNameIndex]->mFlags |= NF_Intrinsic;
}
}
void CName::mfInitTables(void)
{
int i;
for ( i=0; i<8192; i++ )
{
mNameHash[i] = NULL;
}
i = 0;
while(gIntrinsicNames[i].mName[0])
{
mfRegister(gIntrinsicNames[i]);
i++;
}
}
void CName::mfRegister(SNameEntry& sFNE)
{
long hash;
int i, l;
hash = mfGetHash(sFNE.mName);
sFNE.mNext = mNameHash[hash];
mNameHash[hash] = &sFNE;
l = mNames.Num();
while ( l <= sFNE.mNumName )
{
i = mNames.Num();
mNames.AddIndex(1);
mNames[i] = NULL;
l++;
}
if ( mNames[sFNE.mNumName] != NULL )
mDuplicate = sFNE.mNumName;
mNames[sFNE.mNumName] = &sFNE;
}
void CName::mfDisplayHash(void)
{
int i, l, m;
SNameEntry* sFNE;
l = m = 0;
for ( i=0; i<8192; i++ )
{
sFNE = mNameHash[i];
if ( sFNE )
m++;
while ( sFNE )
{
l++;
sFNE = sFNE->mNext;
}
}
iLog->Log( "Hash: %i names, %i/%i hash bins", l, m, 8192);
}
void CName::mfInitSubsystem(void)
{
SNameEntry* sFNE;
SNameEntry* sFNE1;
int i;
CName("None");
assert( mNames.Num() );
if ( mDuplicate )
{
Warning( 0,0,"WARNING: name %i was duplicated", mDuplicate);
return;
}
for ( i=0; i<8192; i++ )
{
sFNE = mNameHash[i];
while ( sFNE )
{
sFNE1 = sFNE->mNext;
if ( sFNE1 )
{
if ( !stricmp(sFNE->mName, sFNE1->mName) )
Warning( 0,0,"WARNING: Name '%s' was duplicated", sFNE->mName);
}
sFNE = sFNE->mNext;
}
}
}
void CName::mfExitSubsystem(void)
{
SNameEntry* sFNE;
int i;
for ( i=0; i<mNames.Num(); i++ )
{
sFNE = mNames[i];
if ( sFNE && !(sFNE->mFlags & NF_Intrinsic) )
DestroyNameEntry(sFNE);
}
mNames.Free();
}
void CName::mfDeleteEntry(int num)
{
SNameEntry* sFNE;
SNameEntry** sFNE1;
int i;
long hash;
sFNE = mNames[num];
assert(sFNE);
assert(!(sFNE->mFlags & NF_Intrinsic));
hash = mfGetHash(sFNE->mName);
sFNE1 = &mNameHash[hash];
while ( *sFNE1 && *sFNE1!=sFNE )
{
sFNE1 = &((*sFNE1)->mNext);
}
if ( !*sFNE1 )
{
Warning( 0,0,"WARNING: Unhashed name '%s'\n", sFNE->mName);
return;
}
*sFNE1 = (*sFNE1)->mNext;
mNames[num] = NULL;
i = mAvailable.Num();
mAvailable.AddIndex(1);
mAvailable[i] = num;
DestroyNameEntry(sFNE);
}

View File

@@ -0,0 +1,75 @@
SNameEntry gIntrinsicNames [] =
{
{ 0, NF_Intrinsic, NULL, "None" },
{ 0, 0, NULL, NULL }
};
long gHashTable[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};

View File

@@ -0,0 +1,311 @@
#ifdef WIN64
#include "WinDef.h"
#endif
#include "NvTriStripObjects.h"
#include "NvTriStrip.h"
#pragma warning(push)
#pragma warning(disable:4018) // signed/unsigned mismatch
#ifdef WIN64 //AMD Port
#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'xxx', possible loss of data
#endif
////////////////////////////////////////////////////////////////////////////////////////
//private data
static unsigned int cacheSize = CACHESIZE_GEFORCE3;// CACHESIZE_GEFORCE1_2;
static bool bStitchStrips = true;
static unsigned int minStripSize = 0;
static bool bListsOnly = false;
////////////////////////////////////////////////////////////////////////////////////////
// SetListsOnly()
//
// If set to true, will return an optimized list, with no strips at all.
//
// Default value: false
//
void SetListsOnly(const bool _bListsOnly)
{
bListsOnly = _bListsOnly;
}
////////////////////////////////////////////////////////////////////////////////////////
// SetCacheSize()
//
// Sets the cache size which the stripfier uses to optimize the data.
// Controls the length of the generated individual strips.
// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
// You may want to play around with this number to tweak performance.
//
// Default value: 16
//
void SetCacheSize(const unsigned int _cacheSize)
{
cacheSize = _cacheSize;
}
////////////////////////////////////////////////////////////////////////////////////////
// SetStitchStrips()
//
// bool to indicate whether to stitch together strips into one huge strip or not.
// If set to true, you'll get back one huge strip stitched together using degenerate
// triangles.
// If set to false, you'll get back a large number of separate strips.
//
// Default value: true
//
void SetStitchStrips(const bool _bStitchStrips)
{
bStitchStrips = _bStitchStrips;
}
////////////////////////////////////////////////////////////////////////////////////////
// SetMinStripSize()
//
// Sets the minimum acceptable size for a strip, in triangles.
// All strips generated which are shorter than this will be thrown into one big, separate list.
//
// Default value: 0
//
void SetMinStripSize(const unsigned int _minStripSize)
{
minStripSize = _minStripSize;
}
////////////////////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
void GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
PrimitiveGroup** primGroups, unsigned short* numGroups)
{
//put data in format that the stripifier likes
int i;
WordVec tempIndices;
tempIndices.resize(in_numIndices);
unsigned short maxIndex = 0;
for(i = 0; i < (int)in_numIndices; i++)
{
tempIndices[i] = in_indices[i];
if(in_indices[i] > maxIndex)
maxIndex = in_indices[i];
}
NvStripInfoVec tempStrips;
NvFaceInfoVec tempFaces;
NvStripifier stripifier;
//do actual stripification
stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
//stitch strips together
IntVec stripIndices;
unsigned int numSeparateStrips = 0;
if(bListsOnly)
{
//if we're outputting only lists, we're done
*numGroups = 1;
(*primGroups) = new PrimitiveGroup[*numGroups];
PrimitiveGroup* primGroupArray = *primGroups;
//count the total number of indices
unsigned int numIndices = 0;
for(i = 0; i < tempStrips.size(); i++)
{
numIndices += tempStrips[i]->m_faces.size() * 3;
}
//add in the list
numIndices += tempFaces.size() * 3;
primGroupArray[0].type = PT_LIST;
primGroupArray[0].numIndices = numIndices;
primGroupArray[0].indices = new unsigned short[numIndices];
//do strips
unsigned int indexCtr = 0;
for(i = 0; i < tempStrips.size(); i++)
{
for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
{
//degenerates are of no use with lists
if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
{
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2;
}
else
{
//we've removed a tri, reduce the number of indices
primGroupArray[0].numIndices -= 3;
}
}
}
//do lists
for(i = 0; i < tempFaces.size(); i++)
{
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2;
}
}
else
{
stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips);
//if we're stitching strips together, we better get back only one strip from CreateStrips()
assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
//convert to output format
*numGroups = numSeparateStrips; //for the strips
if(tempFaces.size() != 0)
(*numGroups)++; //we've got a list as well, increment
(*primGroups) = new PrimitiveGroup[*numGroups];
PrimitiveGroup* primGroupArray = *primGroups;
//first, the strips
int startingLoc = 0;
for(int stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++)
{
int stripLength = 0;
if(!bStitchStrips)
{
//if we've got multiple strips, we need to figure out the correct length
for(i = startingLoc; i < stripIndices.size(); i++)
{
if(stripIndices[i] == -1)
break;
}
stripLength = i - startingLoc;
}
else
stripLength = stripIndices.size();
primGroupArray[stripCtr].type = PT_STRIP;
primGroupArray[stripCtr].indices = new unsigned short[stripLength];
primGroupArray[stripCtr].numIndices = stripLength;
int indexCtr = 0;
for(int i = startingLoc; i < stripLength + startingLoc; i++)
primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i];
//we add 1 to account for the -1 separating strips
//this doesn't break the stitched case since we'll exit the loop
startingLoc += stripLength + 1;
}
//next, the list
if(tempFaces.size() != 0)
{
int faceGroupLoc = (*numGroups) - 1; //the face group is the last one
primGroupArray[faceGroupLoc].type = PT_LIST;
primGroupArray[faceGroupLoc].indices = new unsigned short[tempFaces.size() * 3];
primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3;
int indexCtr = 0;
for(int i = 0; i < tempFaces.size(); i++)
{
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0;
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1;
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2;
}
}
}
//clean up everything
//delete strips
for(i = 0; i < tempStrips.size(); i++)
{
for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
{
delete tempStrips[i]->m_faces[j];
tempStrips[i]->m_faces[j] = NULL;
}
tempStrips[i]->m_faces.resize(0);
delete tempStrips[i];
tempStrips[i] = NULL;
}
//delete faces
for(i = 0; i < tempFaces.size(); i++)
{
delete tempFaces[i];
tempFaces[i] = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////
// RemapIndices()
//
// Function to remap your indices to improve spatial locality in your vertex buffer.
//
// in_primGroups: array of PrimitiveGroups you want remapped
// numGroups: number of entries in in_primGroups
// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
// of acceptable values for indices in your primitive groups.
// remappedGroups: array of remapped PrimitiveGroups
//
// Note that, according to the remapping handed back to you, you must reorder your
// vertex buffer.
//
void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
const unsigned short numVerts, PrimitiveGroup** remappedGroups)
{
(*remappedGroups) = new PrimitiveGroup[numGroups];
//caches oldIndex --> newIndex conversion
int *indexCache;
indexCache = new int[numVerts];
memset(indexCache, -1, sizeof(int)*numVerts);
//loop over primitive groups
unsigned int indexCtr = 0;
for(int i = 0; i < numGroups; i++)
{
unsigned int numIndices = in_primGroups[i].numIndices;
//init remapped group
(*remappedGroups)[i].type = in_primGroups[i].type;
(*remappedGroups)[i].numIndices = numIndices;
(*remappedGroups)[i].indices = new unsigned short[numIndices];
for(int j = 0; j < numIndices; j++)
{
int cachedIndex = indexCache[in_primGroups[i].indices[j]];
if(cachedIndex == -1) //we haven't seen this index before
{
//point to "last" vertex in VB
(*remappedGroups)[i].indices[j] = indexCtr;
//add to index cache, increment
indexCache[in_primGroups[i].indices[j]] = indexCtr++;
}
else
{
//we've seen this index before
(*remappedGroups)[i].indices[j] = cachedIndex;
}
}
}
delete[] indexCache;
}
#pragma warning(pop)

View File

@@ -0,0 +1,131 @@
#ifndef NVTRISTRIP_H
#define NVTRISTRIP_H
#if !defined(NULL) && !defined(LINUX64)
#define NULL 0
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Public interface for stripifier
////////////////////////////////////////////////////////////////////////////////////////
//GeForce1 and 2 cache size
#define CACHESIZE_GEFORCE1_2 16
//GeForce3 cache size
#define CACHESIZE_GEFORCE3 24
enum PrimType
{
PT_LIST,
PT_STRIP,
PT_FAN
};
struct SPrimitiveGroup
{
PrimType type;
unsigned int numIndices;
unsigned int offsIndex;
unsigned int numTris;
unsigned int nFirstFace;
};
struct PrimitiveGroup
{
PrimType type;
unsigned int numIndices;
unsigned short* indices;
////////////////////////////////////////////////////////////////////////////////////////
PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
~PrimitiveGroup()
{
if(indices)
delete[] indices;
indices = NULL;
}
};
////////////////////////////////////////////////////////////////////////////////////////
// SetCacheSize()
//
// Sets the cache size which the stripfier uses to optimize the data.
// Controls the length of the generated individual strips.
// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
// You may want to play around with this number to tweak performance.
//
// Default value: 16
//
void SetCacheSize(const unsigned int cacheSize);
////////////////////////////////////////////////////////////////////////////////////////
// SetStitchStrips()
//
// bool to indicate whether to stitch together strips into one huge strip or not.
// If set to true, you'll get back one huge strip stitched together using degenerate
// triangles.
// If set to false, you'll get back a large number of separate strips.
//
// Default value: true
//
void SetStitchStrips(const bool bStitchStrips);
////////////////////////////////////////////////////////////////////////////////////////
// SetMinStripSize()
//
// Sets the minimum acceptable size for a strip, in triangles.
// All strips generated which are shorter than this will be thrown into one big, separate list.
//
// Default value: 0
//
void SetMinStripSize(const unsigned int minSize);
////////////////////////////////////////////////////////////////////////////////////////
// SetListsOnly()
//
// If set to true, will return an optimized list, with no strips at all.
//
// Default value: false
//
void SetListsOnly(const bool bListsOnly);
////////////////////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
void GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
PrimitiveGroup** primGroups, unsigned short* numGroups);
////////////////////////////////////////////////////////////////////////////////////////
// RemapIndices()
//
// Function to remap your indices to improve spatial locality in your vertex buffer.
//
// in_primGroups: array of PrimitiveGroups you want remapped
// numGroups: number of entries in in_primGroups
// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
// of acceptable values for indices in your primitive groups.
// remappedGroups: array of remapped PrimitiveGroups
//
// Note that, according to the remapping handed back to you, you must reorder your
// vertex buffer.
//
// Credit goes to the MS Xbox crew for the idea for this interface.
//
void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
const unsigned short numVerts, PrimitiveGroup** remappedGroups);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
#ifndef NV_TRISTRIP_OBJECTS_H
#define NV_TRISTRIP_OBJECTS_H
#include <assert.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <vector>
#include <list>
#include "VertexCache.h"
/////////////////////////////////////////////////////////////////////////////////
//
// Types defined for stripification
//
/////////////////////////////////////////////////////////////////////////////////
struct MyVertex {
float x, y, z;
float nx, ny, nz;
};
typedef MyVertex MyVector;
struct MyFace {
int v1, v2, v3;
float nx, ny, nz;
};
class NvFaceInfo {
public:
// vertex indices
NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){
m_v0 = v0; m_v1 = v1; m_v2 = v2;
m_stripId = -1;
m_testStripId = -1;
m_experimentId = -1;
m_bIsFake = bIsFake;
}
// data members are left public
int m_v0, m_v1, m_v2;
int m_stripId; // real strip Id
int m_testStripId; // strip Id in an experiment
int m_experimentId; // in what experiment was it given an experiment Id?
bool m_bIsFake; //if true, will be deleted when the strip it's in is deleted
};
class NvEdgeInfo {
public:
// constructor puts 1 ref on us
NvEdgeInfo (int v0, int v1){
m_v0 = v0;
m_v1 = v1;
m_face0 = NULL;
m_face1 = NULL;
m_nextV0 = NULL;
m_nextV1 = NULL;
// we will appear in 2 lists. this is a good
// way to make sure we delete it the second time
// we hit it in the edge infos
m_refCount = 2;
}
// ref and unref
void Unref () { if (--m_refCount == 0) delete this; }
// data members are left public
unsigned int m_refCount;
NvFaceInfo *m_face0, *m_face1;
int m_v0, m_v1;
NvEdgeInfo *m_nextV0, *m_nextV1;
};
// This class is a quick summary of parameters used
// to begin a triangle strip. Some operations may
// want to create lists of such items, so they were
// pulled out into a class
class NvStripStartInfo {
public:
NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){
m_startFace = startFace;
m_startEdge = startEdge;
m_toV1 = toV1;
}
NvFaceInfo *m_startFace;
NvEdgeInfo *m_startEdge;
bool m_toV1;
};
typedef std::vector<NvFaceInfo*> NvFaceInfoVec;
typedef std::list <NvFaceInfo*> NvFaceInfoList;
typedef std::list <NvFaceInfoVec*> NvStripList;
typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec;
typedef std::vector<unsigned short> WordVec;
typedef std::vector<int> IntVec;
typedef std::vector<MyVertex> MyVertexVec;
typedef std::vector<MyFace> MyFaceVec;
template<class T>
inline void SWAP(T& first, T& second)
{
T temp = first;
first = second;
second = temp;
}
// This is a summary of a strip that has been built
class NvStripInfo {
public:
// A little information about the creation of the triangle strips
NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
m_startInfo(startInfo)
{
m_stripId = stripId;
m_experimentId = experimentId;
visited = false;
m_numDegenerates = 0;
}
// This is an experiment if the experiment id is >= 0
inline bool IsExperiment () const { return m_experimentId >= 0; }
inline bool IsInStrip (const NvFaceInfo *faceInfo) const
{
if(faceInfo == NULL)
return false;
return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
}
bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
// take the given forward and backward strips and combine them together
void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
// mark the triangle as taken by this strip
bool IsMarked (NvFaceInfo *faceInfo);
void MarkTriangle(NvFaceInfo *faceInfo);
// build the strip
void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
// public data members
NvStripStartInfo m_startInfo;
NvFaceInfoVec m_faces;
int m_stripId;
int m_experimentId;
bool visited;
int m_numDegenerates;
};
typedef std::vector<NvStripInfo*> NvStripInfoVec;
//The actual stripifier
class NvStripifier {
public:
// Constructor
NvStripifier();
~NvStripifier();
//the target vertex cache size, the structure to place the strips in, and the input indices
void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength,
const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips);
static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
//static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1);
static bool IsDegenerate(const NvFaceInfo* face);
protected:
WordVec indices;
int cacheSize;
int minStripLength;
float meshJump;
bool bFirstTimeResetPoint;
/////////////////////////////////////////////////////////////////////////////////
//
// Big mess of functions called during stripification
//
/////////////////////////////////////////////////////////////////////////////////
//********************
bool IsMoneyFace(const NvFaceInfo& face);
bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index);
bool IsCW(NvFaceInfo *faceInfo, int v0, int v1);
bool NextIsCW(const int numIndices);
bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2);
static int GetNextIndex(const WordVec &indices, NvFaceInfo *face);
static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end);
void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
float AvgStripSize(const NvStripInfoVec &strips);
int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex);
bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
// let our strip info classes and the other classes get
// to these protected stripificaton methods if they want
friend class NvStripInfo;
};
#endif

View File

@@ -0,0 +1,79 @@
#ifndef VERTEX_CACHE_H
#define VERTEX_CACHE_H
class VertexCache
{
public:
VertexCache(int size)
{
numEntries = size;
entries = new int[numEntries];
for(int i = 0; i < numEntries; i++)
entries[i] = -1;
}
VertexCache() { VertexCache(16); }
~VertexCache() { delete[] entries; entries = 0; }
bool InCache(int entry)
{
bool returnVal = false;
for(int i = 0; i < numEntries; i++)
{
if(entries[i] == entry)
{
returnVal = true;
break;
}
}
return returnVal;
}
int AddEntry(int entry)
{
int removed;
removed = entries[numEntries - 1];
//push everything right one
for(int i = numEntries - 2; i >= 0; i--)
{
entries[i + 1] = entries[i];
}
entries[0] = entry;
return removed;
}
void Clear()
{
memset(entries, -1, sizeof(int) * numEntries);
}
void Copy(VertexCache* inVcache)
{
for(int i = 0; i < numEntries; i++)
{
inVcache->Set(i, entries[i]);
}
}
int At(int index) { return entries[index]; }
void Set(int index, int value) { entries[index] = value; }
private:
int *entries;
int numEntries;
};
#endif

View File

@@ -0,0 +1,18 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "CRE2DQuad.h"
void *CRE2DQuad::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
*Stride = sizeof(m_arrVerts[0]);
switch(ePT)
{
case eSrcPointer_Vert:
return &m_arrVerts[0].xyz.x;
case eSrcPointer_Tex:
return &m_arrVerts[0].st[0];
}
return NULL;
}

View File

@@ -0,0 +1,243 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "I3dengine.h"
void CREBeam::mfPrepare(void)
{
gRenDev->EF_CheckOverflow(0, 0, this);
int Features = gRenDev->GetFeatures();
if (!m_pBuffer)
{
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
IStatObj *pObj = eng->MakeObject(m_ModelName.c_str(), NULL, evs_ShareAndSortForCache, false, false);
m_pBuffer = pObj->GetLeafBuffer();
if (!m_pBuffer)
{
gRenDev->m_RP.m_pRE = NULL;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
return;
}
Vec3d Mins = m_pBuffer->m_vBoxMin;
Vec3d Maxs = m_pBuffer->m_vBoxMax;
m_fLengthScale = Maxs.x;
m_fWidthScale = Maxs.z;
}
CLeafBuffer *lb = m_pBuffer;
CMatInfo *mi = &(*lb->m_pMats)[0];
gRenDev->m_RP.m_pShader = (SShader *)mi->shaderItem.m_pShader->GetTemplate(-1);
gRenDev->m_RP.m_pShaderResources = mi->shaderItem.m_pShaderResources;
gRenDev->m_RP.m_pRE = mi->pRE;
// Choose appropriate shader technique depend on some input parameters
if (gRenDev->m_RP.m_pShader->m_HWTechniques.Num())
{
int nHW = gRenDev->EF_SelectHWTechnique(gRenDev->m_RP.m_pShader);
if (nHW >= 0)
gRenDev->m_RP.m_pCurTechnique = gRenDev->m_RP.m_pShader->m_HWTechniques[nHW];
else
gRenDev->m_RP.m_pCurTechnique = NULL;
}
else
gRenDev->m_RP.m_pCurTechnique = NULL;
CCObject *obj = gRenDev->m_RP.m_pCurObject;
obj->m_RE = this;
UParamVal pv;
pv.m_Float = m_fLengthScale;
SShaderParam::SetParam("origlength", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Float = m_fWidthScale;
SShaderParam::SetParam("origwidth", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Float = m_fLength;
SShaderParam::SetParam("length", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Float = m_fStartRadius;
SShaderParam::SetParam("startradius", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Float = m_fEndRadius;
SShaderParam::SetParam("endradius", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Color[0] = m_StartColor[0];
pv.m_Color[1] = m_StartColor[1];
pv.m_Color[2] = m_StartColor[2];
pv.m_Color[3] = m_StartColor[3];
if (m_LightStyle == 0)
{
pv.m_Color[0] = obj->m_Color[0];
pv.m_Color[1] = obj->m_Color[1];
pv.m_Color[2] = obj->m_Color[2];
}
SShaderParam::SetParam("startcolor", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
pv.m_Color[0] = m_EndColor[0];
pv.m_Color[1] = m_EndColor[1];
pv.m_Color[2] = m_EndColor[2];
pv.m_Color[3] = m_EndColor[3];
if (m_LightStyle == 0)
{
pv.m_Color[0] = obj->m_Color[0];
pv.m_Color[1] = obj->m_Color[1];
pv.m_Color[2] = obj->m_Color[2];
}
SShaderParam::SetParam("endcolor", &gRenDev->m_RP.m_pShader->m_PublicParams, pv, -1);
obj->m_ShaderParams = &gRenDev->m_RP.m_pShader->m_PublicParams;
gRenDev->m_RP.m_FirstVertex = mi->nFirstVertId;
gRenDev->m_RP.m_RendNumIndices = mi->nNumIndices;
gRenDev->m_RP.m_RendNumVerts = mi->nNumVerts;
gRenDev->m_RP.m_FirstIndex = mi->nFirstIndexId;
}
bool CREBeam::mfCompile(SShader *ef, char *scr)
{
char* name;
long cmd;
char *params;
char *data;
enum {eModel = 1, eLength, eStartRadius, eEndRadius, eStartColor, eEndColor, eLightStyle};
static tokenDesc commands[] =
{
{eModel, "Model"},
{eStartRadius, "StartRadius"},
{eEndRadius, "EndRadius"},
{eStartColor, "StartColor"},
{eEndColor, "EndColor"},
{eLightStyle, "LightStyle"},
{eLength, "Length"},
{0, 0},
};
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
{
data = NULL;
if (name)
data = name;
else
if (params)
data = params;
switch (cmd)
{
case eModel:
{
m_ModelName = data;
//IStatObj *pObj = eng->MakeObject(data, NULL, 0, false, false);
//m_pBuffer = pObj->GetLeafBuffer();
}
break;
case eStartRadius:
if (!data || !data[0])
{
Warning( 0,0,"missing StartRadius argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fStartRadius = shGetFloat(data);
break;
case eEndRadius:
if (!data || !data[0])
{
Warning( 0,0,"missing EndRadius argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fEndRadius = shGetFloat(data);
break;
case eLightStyle:
if (!data || !data[0])
{
Warning( 0,0,"missing LightStyle argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_LightStyle = shGetInt(data);
break;
case eLength:
if (!data || !data[0])
{
Warning( 0,0,"missing Length argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fLength = shGetFloat(data);
break;
case eStartColor:
if (!data || !data[0])
{
Warning( 0,0,"missing StartColor argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
shGetColor(data, m_StartColor);
break;
case eEndColor:
if (!data || !data[0])
{
Warning( 0,0,"missing EndColor argument for Beam Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
shGetColor(data, m_EndColor);
break;
}
}
if (!m_ModelName.c_str()[0])
return false;
SShaderParam *sp;
sp = new SShaderParam;
strcpy(sp->m_Name, "origlength");
sp->m_Type = eType_FLOAT;
sp->m_Value.m_Float = 10.0f;
m_ShaderParams.AddElem(sp);
sp = new SShaderParam;
strcpy(sp->m_Name, "origwidth");
sp->m_Type = eType_FLOAT;
sp->m_Value.m_Float = 1.0f;
m_ShaderParams.AddElem(sp);
sp = new SShaderParam;
strcpy(sp->m_Name, "startradius");
sp->m_Type = eType_FLOAT;
sp->m_Value.m_Float = 0.1f;
m_ShaderParams.AddElem(sp);
sp = new SShaderParam;
strcpy(sp->m_Name, "endradius");
sp->m_Type = eType_FLOAT;
sp->m_Value.m_Float = 1.0f;
m_ShaderParams.AddElem(sp);
sp = new SShaderParam;
strcpy(sp->m_Name, "startcolor");
sp->m_Type = eType_FCOLOR;
sp->m_Value.m_Color[0] = 1.0f;
sp->m_Value.m_Color[1] = 1.0f;
sp->m_Value.m_Color[2] = 1.0f;
sp->m_Value.m_Color[3] = 1.0f;
m_ShaderParams.AddElem(sp);
sp = new SShaderParam;
strcpy(sp->m_Name, "endcolor");
sp->m_Type = eType_FCOLOR;
sp->m_Value.m_Color[0] = 1.0f;
sp->m_Value.m_Color[1] = 1.0f;
sp->m_Value.m_Color[2] = 1.0f;
sp->m_Value.m_Color[3] = 0.1f;
m_ShaderParams.AddElem(sp);
return true;
}

View File

@@ -0,0 +1,50 @@
#ifndef __CREBEAM_H__
#define __CREBEAM_H__
//=============================================================
class CREBeam : public CRendElement
{
public:
struct CLeafBuffer * m_pBuffer;
float m_fFogScale;
TArray<SShaderParam *> m_ShaderParams;
CFColor m_StartColor;
CFColor m_EndColor;
float m_fStartRadius;
float m_fEndRadius;
int m_LightStyle;
float m_fLength;
float m_fLengthScale;
float m_fWidthScale;
string m_ModelName;
public:
CREBeam()
{
mfSetType(eDATA_Beam);
m_fFogScale = 0;
m_pBuffer = NULL;
m_LightStyle = 0;
m_fLength = 1.0f;
mfUpdateFlags(FCEF_TRANSFORM);
}
virtual ~CREBeam()
{
for (int i=0; i<m_ShaderParams.Num(); i++)
{
SShaderParam *pr = m_ShaderParams[i];
SAFE_DELETE(pr);
}
m_ShaderParams.Free();
}
virtual void mfPrepare();
virtual bool mfCompile(SShader *ef, char *scr);
};
#endif // __CREBEAM_H__

View File

@@ -0,0 +1,157 @@
/*=============================================================================
CClientPoly.cpp : implementation of Client polygons RE.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
#include "RendElement.h"
//===============================================================
TArray<CREClientPoly *> CREClientPoly::mPolysStorage[4];
CRendElement *CREClientPoly::mfCopyConstruct(void)
{
CREClientPoly *cp = new CREClientPoly;
*cp = *this;
return cp;
}
float CREClientPoly::mfDistanceToCameraSquared(const CCObject & thisObject)
{
CRenderer *rd = gRenDev;
if (m_fDistance >= 0)
return m_fDistance;
Vec3d vMid;
vMid.Set(0,0,0);
SColorVert *tv = mVerts;
for (int i=0; i<mNumVerts; i++, tv++)
{
vMid += tv->vert;
}
vMid /= (float)mNumVerts;
vMid += thisObject.GetTranslation();
Vec3d Delta = rd->m_RP.m_ViewOrg - vMid;
float fDist = GetLengthSquared(Delta);
m_fDistance = fDist;
return fDist;
}
void CREClientPoly::mfPrepare(void)
{
CRenderer *rd = gRenDev;
SShader *ef = rd->m_RP.m_pShader;
byte *inds;
int i, n;
SColorVert *tv;
CREClientPoly::mRS.NumRendPolys++;
{
//PROFILE_FRAME_TOTAL(Mesh_REPrepare_Flush3DPoly);
rd->EF_CheckOverflow(mNumVerts, mNumIndices, this);
}
{
//PROFILE_FRAME_TOTAL(Mesh_REPrepare_3DPoly);
int savev = rd->m_RP.m_RendNumVerts;
int savei = rd->m_RP.m_RendNumIndices;
inds = mIndices;
n = rd->m_RP.m_RendNumVerts;
ushort *dinds = &rd->m_RP.m_RendIndices[rd->m_RP.m_RendNumIndices];
for (i=0; i<mNumIndices; i++, dinds++, inds++)
{
*dinds = *inds+n;
}
rd->m_RP.m_RendNumIndices += i;
byte *OffsT, *OffsD;
tv = mVerts;
UPipeVertex ptr = rd->m_RP.m_NextPtr;
switch(rd->m_RP.m_CurVFormat)
{
case VERTEX_FORMAT_P3F_COL4UB_TEX2F:
OffsT = rd->m_RP.m_OffsT + ptr.PtrB;
OffsD = rd->m_RP.m_OffsD + ptr.PtrB;
for (i=0; i<mNumVerts; i++, tv++, ptr.PtrB+=rd->m_RP.m_Stride, OffsT+=rd->m_RP.m_Stride, OffsD+=rd->m_RP.m_Stride)
{
*(Vec3 *)ptr.PtrB = tv->vert;
*(float *)(OffsT) = tv->dTC[0];
*(float *)(OffsT+4) = tv->dTC[1];
*(uint *)OffsD = tv->color.dcolor;
}
break;
default:
assert(false);
}
if (rd->m_RP.m_OffsD && gbRgb)
{
OffsD = rd->m_RP.m_OffsD + rd->m_RP.m_NextPtr.PtrB;
for (i=0; i<mNumVerts; i++, OffsD+=rd->m_RP.m_Stride)
{
*(uint *)(OffsD) = COLCONV(*(uint *)(OffsD));
}
}
gRenDev->m_RP.m_NextPtr = ptr;
gRenDev->m_RP.m_RendNumVerts += mNumVerts;
CREClientPoly::mRS.NumVerts += gRenDev->m_RP.m_RendNumVerts - savev;
CREClientPoly::mRS.NumIndices += gRenDev->m_RP.m_RendNumIndices - savei;
}
}
bool CREClientPoly::mfCullBox(Vec3d& vmin, Vec3d& vmax)
{
CREClientPoly::mRS.NumOccPolys++;
//if(gfCullBox(vmin, vmax))
// return true;
return false;
}
//=======================================================================
SClientPolyStat CREClientPoly::mRS;
void CREClientPoly::mfPrintStat()
{
/* char str[1024];
*gpCurPrX = 4;
sprintf(str, "Num Indices: %i\n", mRS.NumIndices);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Verts: %i\n", mRS.NumVerts);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Render Client Polys: %i\n", mRS.NumRendPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Occluded Client Polys: %i\n", mRS.NumOccPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
gRenDev->mfPrintString ("\nClient Polygons status info:\n", PS_TRANSPARENT | PS_UP);*/
}

View File

@@ -0,0 +1,54 @@
#ifndef __CRECLIENTPOLY_H__
#define __CRECLIENTPOLY_H__
//=============================================================
struct SClientPolyStat
{
int NumOccPolys;
int NumRendPolys;
int NumVerts;
int NumIndices;
};
//#define MAX_CLIENTPOLY_VERTS 16
#define MAX_CLIENTPOLY_VERTS 32
class CREClientPoly : public CRendElement
{
public:
SShader *mEf;
int m_nFogID;
short mNumVerts;
short mNumIndices;
CCObject *m_pObject;
SColorVert mVerts[MAX_CLIENTPOLY_VERTS];
byte mIndices[(MAX_CLIENTPOLY_VERTS-2)*3];
float m_fDistance;
static SClientPolyStat mRS;
static void mfPrintStat();
public:
CREClientPoly()
{
mfSetType(eDATA_ClientPoly);
mNumVerts = 0;
mEf = NULL;
m_pObject = NULL;
mfSetFlags(FCEF_TRANSFORM | FCEF_NEEDFILLBUF);
}
virtual ~CREClientPoly() {};
virtual void mfPrepare();
bool mfCullBox(Vec3d& vmin, Vec3d& vmax);
float mfDistanceToCameraSquared(const CCObject & thisObject);
virtual CRendElement *mfCopyConstruct(void);
static TArray<CREClientPoly *> mPolysStorage[4];
};
#endif // __CRECLIENTPOLY_H__

View File

@@ -0,0 +1,120 @@
/*=============================================================================
CClientPoly2D.cpp : implementation of 2D Client polygons RE.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
//===============================================================
TArray<CREClientPoly2D *> CREClientPoly2D::mPolysStorage;
CRendElement *CREClientPoly2D::mfCopyConstruct(void)
{
CREClientPoly2D *cp = new CREClientPoly2D;
*cp = *this;
return cp;
}
void CREClientPoly2D::mfPrepare(void)
{
CRenderer *rd = gRenDev;
SShader *ef = rd->m_RP.m_pShader;
byte *inds;
int i, n;
SColorVert2D *tv;
CREClientPoly2D::mRS.NumRendPolys++;
int savev = rd->m_RP.m_RendNumVerts;
int savei = rd->m_RP.m_RendNumIndices;
rd->EF_CheckOverflow(mNumVerts, mNumIndices/3, this);
rd->m_RP.m_FlagsPerFlush |= RBSI_DRAWAS2D;
inds = mIndices;
n = rd->m_RP.m_RendNumVerts;
ushort *dinds = &rd->m_RP.m_RendIndices[gRenDev->m_RP.m_RendNumIndices];
for (i=0; i<mNumIndices; i++, dinds++, inds++)
{
*dinds = *inds+n;
}
rd->m_RP.m_RendNumIndices += i;
tv = mVerts;
UPipeVertex ptr = rd->m_RP.m_NextPtr;
byte *OffsT, *OffsD;
switch(rd->m_RP.m_CurVFormat)
{
case VERTEX_FORMAT_TRP3F_COL4UB_TEX2F:
OffsT = rd->m_RP.m_OffsT + ptr.PtrB;
OffsD = rd->m_RP.m_OffsD + ptr.PtrB;
for (i=0; i<mNumVerts; i++, tv++, ptr.PtrB+=rd->m_RP.m_Stride, OffsT+=rd->m_RP.m_Stride, OffsD+=rd->m_RP.m_Stride)
{
*(float *)(ptr.PtrB+0) = tv->vert[0];
*(float *)(ptr.PtrB+4) = tv->vert[1];
*(float *)(ptr.PtrB+8) = 0.0f;
*(float *)(ptr.PtrB+12) = 1.0f;
*(float *)(OffsT) = tv->dTC[0];
*(float *)(OffsT+4) = tv->dTC[1];
*(uint *)OffsD = tv->color.dcolor;
}
break;
default:
assert(false);
}
if (rd->m_RP.m_OffsD && gbRgb)
{
OffsD = rd->m_RP.m_OffsD + rd->m_RP.m_NextPtr.PtrB;
for (i=0; i<mNumVerts; i++, OffsD+=rd->m_RP.m_Stride)
{
*(uint *)(OffsD) = COLCONV(*(uint *)(OffsD));
}
}
rd->m_RP.m_NextPtr = ptr;
rd->m_RP.m_RendNumVerts += mNumVerts;
CREClientPoly2D::mRS.NumVerts += rd->m_RP.m_RendNumVerts - savev;
CREClientPoly2D::mRS.NumIndices += rd->m_RP.m_RendNumIndices - savei;
}
//=======================================================================
SClientPolyStat2D CREClientPoly2D::mRS;
void CREClientPoly2D::mfPrintStat()
{
/* char str[1024];
*gpCurPrX = 4;
sprintf(str, "Num Indices: %i\n", mRS.NumIndices);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Verts: %i\n", mRS.NumVerts);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Render Client Polys: %i\n", mRS.NumRendPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Occluded Client Polys: %i\n", mRS.NumOccPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
gRenDev->mfPrintString ("\nClient Polygons status info:\n", PS_TRANSPARENT | PS_UP);*/
}

View File

@@ -0,0 +1,47 @@
#ifndef __CRECLIENTPOLY2D_H__
#define __CRECLIENTPOLY2D_H__
//=============================================================
struct SClientPolyStat2D
{
int NumOccPolys;
int NumRendPolys;
int NumVerts;
int NumIndices;
};
class CREClientPoly2D : public CRendElement
{
public:
SShader *mEf;
SRenderShaderResources *m_pShaderResources;
short mNumVerts;
short mNumIndices;
SColorVert2D mVerts[16];
byte mIndices[(16-2)*3];
static SClientPolyStat2D mRS;
static void mfPrintStat();
public:
CREClientPoly2D()
{
mfSetType(eDATA_ClientPoly2D);
mNumVerts = 0;
mEf = NULL;
m_pShaderResources = NULL;
mfUpdateFlags(FCEF_TRANSFORM | FCEF_NEEDFILLBUF);
}
virtual ~CREClientPoly2D() {};
virtual void mfPrepare();
virtual CRendElement *mfCopyConstruct(void);
static TArray<CREClientPoly2D *> mPolysStorage;
};
#endif // __CRECLIENTPOLY2D_H__

View File

@@ -0,0 +1,17 @@
#include "RenderPCH.h"
#include "RendElement.h"
void CREDummy::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
bool CREDummy::mfDraw(SShader *ef, SShaderPass *sfm)
{
return true;
}

View File

@@ -0,0 +1,240 @@
/*=============================================================================
CFlare.cpp : implementation of light coronas and flares RE.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
void CopyLightStyle(int dest, int src);
//===============================================================
CRendElement *CREFlareProp::mfCreateWorldRE(SShader *ef, SInpData *ds)
{
return NULL;
}
bool CREFlareGeom::mfCullFlare(CCObject *obj, CREFlareProp *fp)
{
return false;
}
//========================================================================================
// Parsing
bool CREFlareProp::mfCompile(SShader *ef, char *scr)
{
return false;
}
bool CREFlare::mfCompile(SShader *ef, char *scr)
{
char* name;
long cmd;
char *params;
char *data;
enum {eMap = 1, eScale, eRGBStyle, eBlind, eColor, eDistFactor, eDistIntensityFactor, eMinLight, eSizeBlindScale, eSizeBlindBias, eIntensBlindScale, eIntensBlindBias, eLayer, eImportance, eFadeTime, eVisAreaScale};
static tokenDesc commands[] =
{
{eRGBStyle, "RGBStyle"},
{eScale, "Scale"},
{eBlind, "Blind"},
{eSizeBlindScale, "SizeBlindScale"},
{eSizeBlindBias, "SizeBlindBias"},
{eIntensBlindScale, "IntensBlindScale"},
{eIntensBlindBias, "IntensBlindBias"},
{eMinLight, "MinLight"},
{eDistFactor, "DistFactor"},
{eDistIntensityFactor, "DistIntensityFactor"},
{eMap, "Map"},
{eFadeTime, "FadeTime"},
{eColor, "Color"},
{eLayer, "Layer"},
{eImportance, "Importance"},
{eVisAreaScale, "VisAreaScale"},
{0, 0},
};
CFColor col;
while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
{
data = NULL;
if (name)
data = name;
else
if (params)
data = params;
switch (cmd)
{
case eMap:
m_Map = (STexPic *)gRenDev->EF_LoadTexture(data, FT_NORESIZE, 0, eTT_Base);
break;
case eColor:
if (!data || !data[0])
{
Warning( 0,0,"missing Color argument for Light Stage in Shader '%s'\n", ef->m_Name.c_str());
break;
}
shGetColor(data, m_fColor);
break;
case eRGBStyle:
if (!data || !data[0])
{
Warning( 0,0,"missing RgbStyle argument for Light Stage in Shader '%s'\n", ef->m_Name.c_str());
break;
}
if (!stricmp(data, "Poly"))
m_eLightRGB = eLIGHT_Poly;
else
if (!stricmp(data, "Identity"))
m_eLightRGB = eLIGHT_Identity;
else
if (!strnicmp(data, "FromObj", 7) || !stricmp(data, "FromLight"))
m_eLightRGB = eLIGHT_Object;
else
if (!stricmp(data, "LightStyle"))
{
m_eLightRGB = eLIGHT_Style;
m_Color = CFColor(1.0f);
if (!params || !params[0])
{
Warning( 0,0,"missing RgbStyle LightStyle value in Shader '%s' (use 0)\n", ef->m_Name.c_str());
m_LightStyle = 0;
}
else
m_LightStyle = shGetInt(params);
}
else
if (!stricmp(data, "Fixed"))
{
m_eLightRGB = eLIGHT_Fixed;
if (!params || !params[0])
{
Warning( 0,0,"missing RgbStyle Fixed value in Shader '%s' (use 1.0)\n", ef->m_Name.c_str());
m_Color = CFColor(1.0f);
}
else
{
CFColor col;
shGetColor(params, col);
m_Color = col;
}
}
else
m_eLightRGB = eLIGHT_Identity;
break;
case eScale:
if (!name)
m_fScaleCorona = shGetFloat(data);
else
{
TArray<SParam> Params;
gRenDev->m_cEF.mfCompileParam(params, ef, &Params);
if (Params.Num())
m_pScaleCoronaParams = Params[0].m_Comps[0];
}
break;
case eBlind:
m_bBlind = true;
break;
case eImportance:
m_Importance = shGetInt(data);
break;
case eFadeTime:
m_fFadeTime = shGetFloat(data);
break;
case eSizeBlindScale:
m_fSizeBlindScale = shGetFloat(data);
break;
case eSizeBlindBias:
m_fSizeBlindBias = shGetFloat(data);
break;
case eIntensBlindScale:
m_fIntensBlindScale = shGetFloat(data);
break;
case eIntensBlindBias:
m_fIntensBlindBias = shGetFloat(data);
break;
case eMinLight:
m_fMinLight = shGetFloat(data);
break;
case eDistFactor:
m_fDistSizeFactor = shGetFloat(data);
break;
case eVisAreaScale:
m_fVisAreaScale = shGetFloat(data);
break;
case eDistIntensityFactor:
m_fDistIntensityFactor = shGetFloat(data);
break;
case eLayer:
{
if (!m_Pass)
m_Pass = new SShaderPassHW;
gRenDev->m_cEF.mfCompileLayer(ef, 0, params, m_Pass);
}
break;
}
}
return true;
}
void CREFlare::mfPrepare(void)
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
switch(m_eLightRGB)
{
case eLIGHT_Identity:
m_Color = CFColor(1.0f);
break;
case eLIGHT_Style:
{
if (m_LightStyle>=0 && m_LightStyle<CLightStyle::m_LStyles.Num() && CLightStyle::m_LStyles[m_LightStyle])
{
CLightStyle *ls = CLightStyle::m_LStyles[m_LightStyle];
ls->mfUpdate(gRenDev->m_RP.m_RealTime);
m_Color = m_fColor * ls->m_fIntensity;
}
}
break;
case eLIGHT_Object:
if (gRenDev->m_RP.m_pCurObject)
m_Color = gRenDev->m_RP.m_pCurObject->m_Color;
else
m_Color = CFColor(1.0f);
break;
}
}

View File

@@ -0,0 +1,190 @@
#ifndef __CREFLARES_H__
#define __CREFLARES_H__
//=================================================
// Flares
struct SFlareFrame
{
int mFrame;
float mDecayTime;
bool mbVis;
int mX;
int mY;
float mDepth;
CFColor mColor;
float mScale;
};
class CREFlareProp;
class CREFlareGeom : public CRendElement
{
friend class CRender3D;
public:
SFlareFrame mFlareFr[8];
CFColor mColor;
Vec3d mNormal;
int mLightStyle;
int mDLightStyle;
float mBreakTime;
float mEndBreakTime;
float mfGetScale(float rtime)
{
float scale = 1.0f;
if (mBreakTime && rtime+0.01>=mBreakTime && mEndBreakTime>rtime)
{
float time = rtime - mBreakTime;
if (time<0.25)
{
scale = 1 - time*4;
}
else
{
time = mEndBreakTime - rtime;
if (time<1)
scale= 1 - time;
else
scale = 0;
}
return scale;
}
return -1;
}
CREFlareGeom()
{
mfSetType(eDATA_FlareGeom);
mfUpdateFlags(FCEF_TRANSFORM);
}
virtual ~CREFlareGeom()
{
}
void mfCheckVis(CFColor &col, CCObject *obj);
bool mfCullFlare(CCObject *obj, CREFlareProp *fp);
};
enum ELightRGB
{
eLIGHT_Identity,
eLIGHT_Fixed,
eLIGHT_Poly,
eLIGHT_Style,
eLIGHT_Object,
};
enum EEmitLight
{
eEMIT_Poly,
eEMIT_Point,
};
class CREFlareProp : public CRendElement
{
friend class CRender3D;
public:
SShader *FlareShader;
ELightRGB eLightRGB;
float LightColorScale;
CFColor LightColor;
int LightStyle;
float offsLight;
EEmitLight eLightEmit;
CREFlareProp()
{
mfSetType(eDATA_FlareProp);
mfUpdateFlags(FCEF_TRANSFORM);
LightColorScale = 1;
eLightEmit = eEMIT_Point;
LightStyle = 0;
FlareShader = 0;
eLightRGB = eLIGHT_Identity;
}
virtual ~CREFlareProp()
{
}
virtual bool mfCompile(SShader *ef, char *scr);
virtual CRendElement *mfCreateWorldRE(SShader *ef, SInpData *ds);
};
class CREFlare : public CRendElement
{
friend class CRender3D;
friend class CGLRenderer;
public:
Vec3d mNormal;
float m_fScaleCorona;
SParamComp *m_pScaleCoronaParams;
float m_fMinLight;
float m_fDistSizeFactor;
float m_fDistIntensityFactor;
bool m_bBlind;
float m_fSizeBlindBias;
float m_fSizeBlindScale;
float m_fIntensBlindBias;
float m_fIntensBlindScale;
float m_fFadeTime;
float m_fVisAreaScale;
STexPic *m_Map;
ELightRGB m_eLightRGB;
int m_LightStyle;
CFColor m_fColor;
int m_UpdateFrame;
int m_nFrameQuery;
SShaderPassHW *m_Pass;
int m_Importance;
CREFlare()
{
mfSetType(eDATA_Flare);
mfUpdateFlags(FCEF_TRANSFORM);
m_Map = NULL;
m_fMinLight = 0.0f;
m_eLightRGB = eLIGHT_Identity;
m_fColor = Col_White;
m_UpdateFrame = -1;
m_fDistSizeFactor = 1.0f;
m_fDistIntensityFactor = 1.0f;
m_fSizeBlindBias = 0;
m_nFrameQuery = -1;
m_fSizeBlindScale = 1.0f;
m_fIntensBlindBias = 0;
m_fIntensBlindScale = 1.0f;
m_fVisAreaScale = 1.0f;
m_fFadeTime = -1.0f;
m_bBlind = false;
m_fScaleCorona = 0.6f;
m_pScaleCoronaParams = NULL;
m_Pass = NULL;
m_Importance = 1;
}
virtual ~CREFlare()
{
if (m_Map)
{
m_Map->Release(false);
m_Map = NULL;
}
SAFE_DELETE(m_Pass);
}
virtual bool mfCompile(SShader *ef, char *scr);
virtual void mfPrepare(void);
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
void mfDrawCorona(SShader *ef, CFColor &col);
void mfDrawFlares(SShader *ef, CFColor &col);
bool mfCheckVis(CCObject *obj);
};
#endif // __CREFLARES_H__

View File

@@ -0,0 +1,17 @@
#include "RenderPCH.h"
#include "RendElement.h"
#if !defined(LINUX)
void CREFlashBang::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_DRAWAS2D;
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
#endif // !defined(LINUX)

View File

@@ -0,0 +1,24 @@
#include "RenderPCH.h"
#include "RendElement.h"
void CREGlare:: mfInit()
{
m_GlareWidth = 128;
m_GlareHeight = 128;
m_fGlareAmount=0;
mfSetType(eDATA_Glare);
mfUpdateFlags(FCEF_TRANSFORM);
}
void CREGlare::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 4;
gRenDev->m_RP.m_FirstVertex = 0;
}

View File

@@ -0,0 +1,39 @@
#ifndef __CREGLARE_H__
#define __CREGLARE_H__
//=============================================================
struct SByteColor
{
byte r,g,b,a;
};
struct SLongColor
{
unsigned long r,g,b,a;
};
class CREGlare : public CRendElement
{
public:
int m_GlareWidth;
int m_GlareHeight;
float m_fGlareAmount;
public:
CREGlare()
{
mfInit();
}
void mfInit();
virtual ~CREGlare()
{
}
virtual void mfPrepare();
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
};
#endif // __CREGLARE_H__

View File

@@ -0,0 +1,43 @@
/*
=======================================================================
FILE : CREHDRProcess.cpp
DESC : HDR processing render element
PROJ : Crytek Engine
CODER: Andrey Honich
=======================================================================
*/
#include "RenderPCH.h"
// constructor/destructor
CREHDRProcess::CREHDRProcess()
{
// setup screen process renderer type
mfSetType(eDATA_HDRProcess);
mfUpdateFlags(FCEF_TRANSFORM);
}
CREHDRProcess::~CREHDRProcess()
{
};
// prepare screen processing
void CREHDRProcess:: mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_DRAWAS2D;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
void CREHDRProcess::mfReset()
{
}
void CREHDRProcess::mfActivate(int iProcess)
{
}

View File

@@ -0,0 +1,39 @@
/*
=====================================================================
FILE : CREHDRProcess.h
DESC : HDR processing render element
PROJ : Crytek Engine
CODER: Andrey Honich
=====================================================================
*/
#ifndef __CREHDRPROCESS_H__
#define __CREHDRPROCESS_H__
// screen processing render element
class CREHDRProcess : public CRendElement
{
friend class CD3D9Renderer;
friend class CGLRenderer;
public:
// constructor/destructor
CREHDRProcess();
virtual ~CREHDRProcess();
// prepare screen processing
virtual void mfPrepare();
// render screen processing
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
// begin screen processing
virtual void mfActivate(int iProcess);
// reset
virtual void mfReset(void);
};
#endif

View File

@@ -0,0 +1,31 @@
#ifndef __CREHEAT_H__
#define __CREHEAT_H__
//=============================================================
class CREHeat : public CRendElement
{
public:
int m_HeatWidth;
int m_HeatHeight;
public:
CREHeat()
{
m_HeatWidth = CRenderer::CV_r_heatsize;
m_HeatHeight = CRenderer::CV_r_heatsize;
mfSetType(eDATA_Heat);
mfUpdateFlags(FCEF_TRANSFORM);
}
virtual ~CREHeat()
{
}
virtual void mfPrepare();
virtual bool mfDraw(SShader *ef, SShadeLayer *sfm);
};
#endif // __CREHEAT_H__

View File

@@ -0,0 +1,96 @@
#if !defined(LINUX)
#include "stdafx.h"
#include "RendElement.h"
#include "CREMotionBlur.h"
#ifdef OPENGL
#include "..\..\XRenderOGL\GL_Renderer.h"
#endif
void CREMotionBlur::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_DynLMask |= m_DynMask;
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
bool CREMotionBlur::mfDraw(SShader *ef, SShaderPass *sfm)
{
gRenDev->ResetToDefault();
static int counter=0;
gRenDev->EnableBlend(true);
gRenDev->SetBlendMode();
gRenDev->Set2DMode(true,100,100);
gRenDev->EnableDepthWrites(false);
gRenDev->EnableDepthTest(false);
for(int pass=-1; pass>-16 ; pass--)
{
if(!sfm->m_TUnits[0]->mfSetTexture(counter+pass))
break;
gRenDev->SetEnviMode(R_MODE_MODULATE);
gRenDev->SetMaterialColor(1,1,1,1.f/(float)fabs(pass+1));
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
100, 100, 0, 1,1.f-1,
100, 0, 0, 1,1.f-0,
0, 100, 0, 0,1.f-1,
0, 0, 0, 0,1.f-0,
};
gRenDev->PushMatrix();
gRenDev->TranslateMatrix(Vec3d(50,50,0));
// scale
if(m_nEffectType == 1)
{
float scale = 1.0f-(float)fabs(pass/16.f)/3.0f;
gRenDev->ScaleMatrix(scale,scale,0);
}
if(m_nEffectType == 2)
{
float scale = 1.f+(float)fabs(pass/16.f)/3;
gRenDev->ScaleMatrix(scale,scale,0);
}
// rotation
else if(m_nEffectType == 3)
{
gRenDev->RotateMatrix(Vec3d(0,0,pass&1 ? (float)fabs(pass/16.f)*4.0f : -(float)fabs(pass/16.f)*4.0f));
}
else if(m_nEffectType == 4)
{
gRenDev->RotateMatrix(Vec3d(0,0,pass&1 ? (float)fabs(pass/16.f)*40 : -(float)fabs(pass/16.f)*40));
}
// translation
else if(m_nEffectType == 5)
{
gRenDev->TranslateMatrix(Vec3d(pass&1 ? (float)fabs(pass/16.f)*4.0f : -(float)fabs(pass/16.f)*4.0f,0,0));
}
else if(m_nEffectType == 6)
{
gRenDev->TranslateMatrix(Vec3d(0,pass&1 ? (float)fabs(pass/16.f)*4.0f : -(float)fabs(pass/16.f)*4.0f,0));
}
gRenDev->TranslateMatrix(Vec3d(-50,-50,0));
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),4);
gRenDev->PopMatrix();
}
counter++;
gRenDev->Set2DMode(false,100,100);
gRenDev->ResetToDefault();
return true;
}
#endif // !defined(LINUX)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,756 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "CREOcean.h"
#include "../NvTriStrip/NVTriStrip.h"
#include "I3dengine.h"
SREOceanStats CREOcean::m_RS;
CREOcean *CREOcean::m_pStaticOcean = NULL;
DEFINE_ALIGNED_DATA( float, CREOcean::m_HX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA( float, CREOcean::m_HY[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA( float, CREOcean::m_NX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA( float, CREOcean::m_NY[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA( float, CREOcean::m_DX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA( float, CREOcean::m_DY[OCEANGRID][OCEANGRID], 16 );
CREOcean::~CREOcean()
{
m_pStaticOcean = NULL;
if (m_pBuffer)
{
gRenDev->ReleaseBuffer(m_pBuffer);
m_pBuffer = NULL;
}
SAFE_DELETE_ARRAY(m_HMap);
for (int i=0; i<NUM_LODS; i++)
{
m_pIndices[i].Free();
}
}
float CREOcean::GetWaterZElevation(float fX, float fY)
{
if (!m_HMap)
return 0;
CRenderer *r = gRenDev;
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
float fSize = (float)CRenderer::CV_r_oceansectorsize;
float fHeightScale = (float)CRenderer::CV_r_oceanheightscale;
float fWaterLevel = eng->GetWaterLevel();
float fHScale = fabsf(gRenDev->m_RP.m_ViewOrg.z-fWaterLevel);
float fMaxDist = eng->GetMaxViewDistance() / 1.0f;
float fGrid = (float)OCEANGRID;
float fZH = GetHMap(fX, fY);
if (fZH >= fWaterLevel)
return fWaterLevel;
float fXPart = fX / fSize;
float fYPart = fY / fSize;
float fXLerp = (fXPart - (int)fXPart) * fGrid;
float fYLerp = (fYPart - (int)fYPart) * fGrid;
int nXMin = (int)fXLerp;
int nXMax = nXMin+1;
int nYMin = (int)fYLerp;
int nYMax = nYMin+1;
fXLerp = fXLerp - (int)fXLerp;
fYLerp = fYLerp - (int)fYLerp;
if (fHScale < 5.0f)
fHScale = LERP(0.1f, 0.5f, fHScale/5.0f);
else
if (fHScale < 20)
fHScale = LERP(0.5f, 1.0f, (fHScale-5.0f)/15.0f);
else
fHScale = 1.0f;
float fZ00 = -m_HX[nYMin][nXMin] * fHScale;
float fZ01 = -m_HX[nYMin][nXMax] * fHScale;
float fZ10 = -m_HX[nYMax][nXMin] * fHScale;
float fZ11 = -m_HX[nYMax][nXMax] * fHScale;
float fZ0 = LERP(fZ00, fZ01, fXLerp);
float fZ1 = LERP(fZ10, fZ11, fXLerp);
float fZ = LERP(fZ0, fZ1, fYLerp);
//fZ *= fHeightScale;
float fHeightDelta = fWaterLevel - fZH;
fHeightScale *= CLAMP(fHeightDelta * 0.066f, 0, 1);
return fZ * fHeightScale + fWaterLevel;
}
void CREOcean::PrepareHMap()
{
int nDim=0;
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
m_nHMUnitSize = eng->GetHeightMapUnitSize();
int nExp = 8;
m_fExpandHMap = (float)nExp;
m_fExpandHM = (float)m_nHMUnitSize * (float)nExp;
m_fInvHMUnitSize = 1.0f / (float)m_nHMUnitSize;
m_fTerrainSize = (float)eng->GetTerrainSize();
eng->MakeUnderWaterSmoothHMap(m_nHMUnitSize);
ushort *shm = eng->GetUnderWaterSmoothHMap(nDim);
if(!nDim)
return; // terrain not present
float fWaterLevel = eng->GetWaterLevel();
if (m_HMap)
delete [] m_HMap;
int nDimO = nDim+nExp*2;
m_nHMapSize = nDimO;
m_HMap = new float [nDimO*nDimO];
float f;
for (int y=-nExp; y<nDim+nExp; y++)
{
for (int x=-nExp; x<nDim+nExp; x++)
{
if (x>0 && x<nDim-1 && y>0 && y<nDim-1)
m_HMap[(y+nExp)*nDimO+x+nExp] = (float)shm[y*nDim+x] / 256.0f;
else
{
int nX = x;
int nY = y;
float fLerpX = -1.0f;
float fLerpY = -1.0f;
if (nX<=0)
nX = 1;
else
if (nX>=nDim-1)
nX = nDim-2;
if (nY<=0)
nY = 1;
else
if (nY>=nDim-1)
nY = nDim-2;
f = (float)shm[nY*nDim+nX] / 256.0f;
if (nX != x)
fLerpX = 1.0f - fabsf((float)(nX-x)) / (float)(nExp+1);
if (nY != y)
fLerpY = 1.0f - fabsf((float)(nY-y)) / (float)(nExp+1);
float fX, fY;
if (fLerpX >= 0)
fX = LERP(fWaterLevel/2.0f, f, fLerpX);
if (fLerpY >= 0)
fY = LERP(fWaterLevel/2.0f, f, fLerpY);
if (fLerpX >= 0 && fLerpY >= 0)
m_HMap[(y+nExp)*nDimO+x+nExp] = (fX + fY) / 2.0f;
else
if (fLerpX >= 0)
m_HMap[(y+nExp)*nDimO+x+nExp] = fX;
else
if (fLerpY >= 0)
m_HMap[(y+nExp)*nDimO+x+nExp] = fY;
else
m_HMap[(y+nExp)*nDimO+x+nExp] = f;
}
}
}
}
void CREOcean::mfPrepare()
{
CRenderer *rd = gRenDev;
if (m_nFrameLoad != rd->m_nFrameLoad)
{
m_nFrameLoad = rd->m_nFrameLoad;
PrepareHMap();
}
rd->EF_CheckOverflow(0, 0, this);
Update(rd->m_RP.m_RealTime * m_fSpeed);
double time0 = 0;
ticks(time0);
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
float fWaterLevel = eng->GetWaterLevel();
float fHScale = fabsf(gRenDev->m_RP.m_ViewOrg.z-fWaterLevel);
if (fHScale < 5.0f)
fHScale = LERP(0.1f, 0.5f, fHScale/5.0f);
else
if (fHScale < 20)
fHScale = LERP(0.5f, 1.0f, (fHScale-5.0f)/15.0f);
else
fHScale = 1.0f;
m_MinBound.Set(9999.0f, 9999.0f, 9999.0f);
m_MaxBound.Set(-9999.0f, -9999.0f, -9999.0f);
if (!m_pBuffer)
m_pBuffer = gRenDev->CreateBuffer((OCEANGRID+1)*(OCEANGRID+1), VERTEX_FORMAT_P3F_N, "Ocean", true);
rd->UpdateBuffer(m_pBuffer, NULL, 0, 0, 0, 1);
static const float fScale = 1.0f / (float)OCEANGRID;
struct_VERTEX_FORMAT_P3F_N *pVertices = (struct_VERTEX_FORMAT_P3F_N *)m_pBuffer->m_VS[VSF_GENERAL].m_VData;
for(int vy=0; vy<OCEANGRID+1; vy++)
{
int y = vy & (OCEANGRID-1);
for(int vx=0; vx<(OCEANGRID+1); vx++)
{
int x = vx & (OCEANGRID-1);
m_Pos[vy][vx][0] = vx * fScale + m_DX[y][x] * m_fChoppyWaveFactor;
m_Pos[vy][vx][1] = vy * fScale + m_DY[y][x] * m_fChoppyWaveFactor;
pVertices->xyz.x = m_Pos[vy][vx][0];
pVertices->xyz.y = m_Pos[vy][vx][1];
float fZ = -m_HX[y][x] * fHScale;
pVertices->xyz.z = fZ;
m_MinBound.x = min(m_Pos[vy][vx][0], m_MinBound.x);
m_MinBound.y = min(m_Pos[vy][vx][1], m_MinBound.y);
m_MinBound.z = min(fZ, m_MinBound.z);
m_MaxBound.x = max(m_Pos[vy][vx][0], m_MaxBound.x);
m_MaxBound.y = max(m_Pos[vy][vx][1], m_MaxBound.y);
m_MaxBound.z = max(fZ, m_MaxBound.z);
m_Normals[vy][vx] = Vec3d(m_NX[y][x], m_NY[y][x], 64.0f);
pVertices->normal = m_Normals[vy][vx];
m_Normals[vy][vx].NormalizeFast();
pVertices++;
}
}
unticks(time0);
m_RS.m_StatsTimeUpdateVerts = (float)(time0*1000.0*g_SecondsPerCycle);
UpdateTexture();
rd->m_RP.m_pRE = this;
rd->m_RP.m_RendNumIndices = 0;
rd->m_RP.m_RendNumVerts = (OCEANGRID+1)*(OCEANGRID+1);
rd->m_RP.m_FirstVertex = 0;
}
int CREOcean::GetLOD(Vec3d camera, Vec3d pos)
{
float dist = (pos-camera).GetLength();
dist /= CRenderer::CV_r_oceanloddist;
return (int)CLAMP(dist, 0.0f, (float)(NUM_LODS-1));
}
void *CREOcean::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
switch(ePT)
{
case eSrcPointer_Vert:
{
struct_VERTEX_FORMAT_P3F_N *pVertices = (struct_VERTEX_FORMAT_P3F_N *)m_pBuffer->m_VS[VSF_GENERAL].m_VData;
*Stride = sizeof(struct_VERTEX_FORMAT_P3F_N);
return &pVertices->xyz.x;
}
case eSrcPointer_Normal:
{
struct_VERTEX_FORMAT_P3F_N *pVertices = (struct_VERTEX_FORMAT_P3F_N *)m_pBuffer->m_VS[VSF_GENERAL].m_VData;
*Stride = sizeof(struct_VERTEX_FORMAT_P3F_N);
return &pVertices->normal.x;
}
}
return NULL;
}
void CREOcean::GenerateGeometry()
{
m_pBuffer = gRenDev->CreateBuffer((OCEANGRID+1)*(OCEANGRID+1), VERTEX_FORMAT_P3F_N, "Ocean", true);
for (int lod=0; lod<NUM_LODS; lod++)
{
int nl = 1<<lod;
// set indices
int iIndex = 0;
int yStep = (OCEANGRID+1) * nl;
for(int a=0; a<(OCEANGRID+1)-1; a+=nl )
{
for(int i=0; i<(OCEANGRID+1); i+=nl, iIndex+=nl )
{
m_pIndices[lod].AddElem(iIndex);
m_pIndices[lod].AddElem(iIndex + yStep);
}
int iNextIndex = (a+nl) * (OCEANGRID+1);
if(a < (OCEANGRID+1)-1-nl)
{
m_pIndices[lod].AddElem(iIndex + yStep - nl);
m_pIndices[lod].AddElem(iNextIndex);
}
iIndex = iNextIndex;
}
m_pIndices[lod].Shrink();
}
}
void CREOcean::SmoothLods_r(SOceanSector *os, float fSize, int minLod)
{
if (os->m_Frame != gRenDev->m_cEF.m_Frame)
return;
if (os->nLod > minLod+1)
{
os->nLod = minLod+1;
SOceanSector *osLeft;
SOceanSector *osRight;
SOceanSector *osTop;
SOceanSector *osBottom;
// Left
osLeft = GetSectorByPos(os->x-fSize, os->y, false);
// Right
osRight = GetSectorByPos(os->x+fSize, os->y, false);
// Top
osTop = GetSectorByPos(os->x, os->y-fSize, false);
// Bottom
osBottom = GetSectorByPos(os->x, os->y+fSize, false);
if (osLeft)
SmoothLods_r(osLeft, fSize, os->nLod);
if (osRight)
SmoothLods_r(osRight, fSize, os->nLod);
if (osTop)
SmoothLods_r(osTop, fSize, os->nLod);
if (osBottom)
SmoothLods_r(osBottom, fSize, os->nLod);
}
}
void CREOcean::LinkVisSectors(float fSize)
{
for (int i=0; i<m_VisOceanSectors.Num(); i++)
{
SOceanSector *os = m_VisOceanSectors[i];
SOceanSector *osLeft;
SOceanSector *osRight;
SOceanSector *osTop;
SOceanSector *osBottom;
// Left
osLeft = GetSectorByPos(os->x-fSize, os->y, false);
// Right
osRight = GetSectorByPos(os->x+fSize, os->y, false);
// Top
osTop = GetSectorByPos(os->x, os->y-fSize, false);
// Bottom
osBottom = GetSectorByPos(os->x, os->y+fSize, false);
if (osLeft)
SmoothLods_r(osLeft, fSize, os->nLod);
if (osRight)
SmoothLods_r(osRight, fSize, os->nLod);
if (osTop)
SmoothLods_r(osTop, fSize, os->nLod);
if (osBottom)
SmoothLods_r(osBottom, fSize, os->nLod);
}
}
void CREOcean::PostLoad(unsigned long ulSeed, float fWindDirection, float fWindSpeed, float fWaveHeight, float fDirectionalDependence, float fChoppyWavesFactor, float fSuppressSmallWavesFactor)
{
m_fWindX = cry_cosf( fWindDirection );
m_fWindY = cry_sinf( fWindDirection );
m_fWindSpeed = fWindSpeed;
m_fWaveHeight = fWaveHeight;
m_fDirectionalDependence = fDirectionalDependence;
m_fChoppyWaveFactor = fChoppyWavesFactor;
m_fSuppressSmallWavesFactor = fSuppressSmallWavesFactor;
m_fLargestPossibleWave = m_fWindSpeed * m_fWindSpeed / m_fGravity;
m_fSuppressSmallWaves = m_fLargestPossibleWave * m_fSuppressSmallWavesFactor;
// init H0
CRERandom kRnd( ulSeed );
float fOneBySqrtTwo = 1.0f / cry_sqrtf(2.0f);
int i, j;
for(j=-OCEANGRID/2; j<=OCEANGRID/2; j++)
{
int y = j + OCEANGRID/2;
for(i=-OCEANGRID/2; i<=OCEANGRID/2; i++)
{
int x = i + OCEANGRID/2;
float rndX = (float)kRnd.GetGauss();
float rndY = (float)kRnd.GetGauss();
rndX *= fOneBySqrtTwo * cry_sqrtf(PhillipsSpectrum(2.0f*PI*i, 2.0f*PI*j));
rndY *= fOneBySqrtTwo * cry_sqrtf(PhillipsSpectrum(2.0f*PI*i, 2.0f*PI*j));
m_H0X[y][x] = rndX;
m_H0Y[y][x] = rndY;
}
}
// precalc length of K
for(j=-OCEANGRID/2; j<OCEANGRID/2; j++)
{
int y = j + OCEANGRID/2;
for(i=-OCEANGRID/2; i<OCEANGRID/2; i++)
{
int x = i + OCEANGRID/2;
float fKLength = cry_sqrtf(sqrf(2.0f*PI*i) + sqrf(2.0f*PI*j));
if( fKLength < 1e-8f )
fKLength = 1e-8f;
m_aKScale[y][x] = 1.0f / fKLength;
}
}
// init angular frequencies
for(j=-OCEANGRID/2; j<OCEANGRID/2; j++)
{
int y = j + OCEANGRID/2;
for(i=-OCEANGRID/2; i<OCEANGRID/2; i++)
{
int x = i + OCEANGRID/2;
float fKLength = cry_sqrtf(sqrf(2.0f*PI*i) + sqrf(2.0f*PI*j));
m_aAngularFreq[y][x] = cry_sqrtf(m_fGravity * fKLength) * cry_tanhf(fKLength * m_fDepth);
}
}
}
void CREOcean::FFT( int iDir, float* real, float* imag )
{
long nn,i,i1,j,k,i2,l,l1,l2;
float c1,c2,treal,timag,t1,t2,u1,u2,z;
nn = OCEANGRID;
// Do the bit reversal
i2 = nn >> 1;
j = 0;
for( i = 0; i < nn - 1; ++i )
{
if( i < j )
{
treal = real[ i ];
timag = imag[ i ];
real[ i ] = real[ j ];
imag[ i ] = imag[ j ];
real[ j ] = treal;
imag[ j ] = timag;
}
k = i2;
while( k <= j )
{
j -= k;
k >>= 1;
}
j += k;
}
// Compute the FFT
c1 = -1.0f;
c2 = 0.0f;
l2 = 1;
for(l=0; l<LOG_OCEANGRID; l++)
{
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for( j = 0; j < l1; ++j )
{
for( i = j; i < nn; i += l2 )
{
i1 = i + l1;
t1 = u1 * real[i1] - u2 * imag[i1];
t2 = u1 * imag[i1] + u2 * real[i1];
real[i1] = real[i] - t1;
imag[i1] = imag[i] - t2;
real[i] += t1;
imag[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = crySqrtf(( 1.0f - c1 ) / 2.0f);
if( 1 == iDir )
{
c2 = -c2;
}
c1 = crySqrtf(( 1.0f + c1 ) / 2.0f);
}
// Scaling for forward transform
if( 1 == iDir )
{
for(i=0; i<nn; ++i)
{
real[i] /= (float) nn;
imag[i] /= (float) nn;
}
}
}
void FFTSSE_64(float* ar, float* ai);
void CREOcean::FFT2D(int iDir, float cmpX[OCEANGRID][OCEANGRID], float cmpY[OCEANGRID][OCEANGRID])
{
float real[OCEANGRID];
float imag[OCEANGRID];
#if !defined(_XBOX) && !defined(WIN64) && !defined(LINUX)
// NOTE: AMD64 port: implement
if ((g_CpuFlags & CPUF_SSE) && CRenderer::CV_r_sse && !(((int)&cmpX[0][0]) & 0xf) && !(((int)&cmpY[0][0]) & 0xf) && OCEANGRID == 64)
{
FFTSSE_64(&cmpY[0][0], &cmpX[0][0]);
return;
}
#endif
int i, j;
// Transform the rows
for(j=0; j<OCEANGRID; j++)
{
for(i=0; i<OCEANGRID; i++)
{
real[i] = cmpX[j][i];
imag[i] = cmpY[j][i];
}
FFT( iDir, real, imag );
for(i=0; i<OCEANGRID; i++)
{
cmpX[j][i] = real[i];
cmpY[j][i] = imag[i];
}
}
// Transform the columns
for(i=0; i<OCEANGRID; i++)
{
for(j=0; j<OCEANGRID; j++)
{
real[j] = cmpX[j][i];
imag[j] = cmpY[j][i];
}
FFT( iDir, real, imag );
for(j=0; j<OCEANGRID; j++)
{
cmpX[j][i] = real[j];
cmpY[j][i] = imag[j];
}
}
}
void CREOcean::Update( float fTime )
{
double time0 = 0;
ticks(time0);
float fK = 2.0f * PI;
for(int j=-OCEANGRID/2; j<OCEANGRID/2; j++)
{
int jn = j & (OCEANGRID-1);
for(int i=-OCEANGRID/2; i<OCEANGRID/2; i++)
{
int x = i + OCEANGRID/2;
int y = j + OCEANGRID/2;
unsigned int val = (int)(m_aAngularFreq[y][x] * 1024.0f / (PI*2) * fTime);
float fSin = gRenDev->m_RP.m_tSinTable[val&0x3ff];
float fCos = gRenDev->m_RP.m_tSinTable[(val+512)&0x3ff];
int x1 = -i + OCEANGRID/2;
int y1 = -j + OCEANGRID/2;
float hx = (m_H0X[y][x] + m_H0X[y1][x1]) * fCos -
(m_H0Y[y][x] + m_H0Y[y1][x1]) * fSin;
float hy = (m_H0X[y][x] - m_H0X[y1][x1]) * fSin +
(m_H0Y[y][x] - m_H0Y[y1][x1]) * fCos;
int in = i & (OCEANGRID-1);
// update height
m_HX[jn][in] = hx;
m_HY[jn][in] = hy;
// update normal
float fKx = fK * i;
float fKy = fK * j;
m_NX[jn][in] = (-hy * fKx - hx * fKy);
m_NY[jn][in] = ( hx * fKx - hy * fKy);
// update displacement vector for choppy waves
fKx *= m_aKScale[y][x];
fKy *= m_aKScale[y][x];
m_DX[jn][in] = ( hy * fKx + hx * fKy);
m_DY[jn][in] = (-hx * fKx + hy * fKy);
}
}
unticks(time0);
m_RS.m_StatsTimeFFTTable = (float)(time0*1000.0*g_SecondsPerCycle);
ticks(time0);
FFT2D(-1, m_HX, m_HY);
FFT2D(-1, m_NX, m_NY);
FFT2D(-1, m_DX, m_DY);
unticks(time0);
m_RS.m_StatsTimeFFT = (float)(time0*1000.0*g_SecondsPerCycle);
}
bool CREOcean::mfCompile(SShader *ef, char *scr)
{
char* name;
long cmd;
char *params;
char *data;
enum {eSeed = 1, eSpeed, eGravity, eDepth, eWindSpeed, eWindDirection, eWaveHeight, eDirectionalDependence, eChoppyWaveFactor, eSuppressSmallWavesFactor};
static tokenDesc commands[] =
{
{eSpeed, "Speed"},
{eGravity, "Gravity"},
{eDepth, "Depth"},
{eWindDirection, "WindDirection"},
{eWindSpeed, "WindSpeed"},
{eWaveHeight, "WaveHeight"},
{eDirectionalDependence, "DirectionalDependence"},
{eChoppyWaveFactor, "ChoppyWaveFactor"},
{eSuppressSmallWavesFactor, "SuppressSmallWavesFactor"},
{0, 0},
};
float fWindDirection = 90.0f;
float fWindSpeed = m_fWindSpeed;
float fWaveHeight = m_fWaveHeight;
float fDirectionalDependence = m_fDirectionalDependence;
float fChoppyWaveFactor = m_fChoppyWaveFactor;
float fSuppressSmallWavesFactor = m_fSuppressSmallWavesFactor;
m_fSpeed = 1.0f;
m_fGravity = 9.81f;
m_fDepth = 10;
while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
{
data = NULL;
if (name)
data = name;
else
if (params)
data = params;
switch (cmd)
{
case eGravity:
if (!data || !data[0])
{
Warning( 0,0,"missing Gravity argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fGravity = shGetFloat(data);
break;
case eDepth:
if (!data || !data[0])
{
Warning( 0,0,"missing Depth argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fDepth = shGetFloat(data);
break;
case eSpeed:
if (!data || !data[0])
{
Warning( 0,0,"missing Speed argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
m_fSpeed = shGetFloat(data);
break;
case eWindDirection:
if (!data || !data[0])
{
Warning( 0,0,"missing WindDirection argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fWindDirection = shGetFloat(data);
break;
case eWindSpeed:
if (!data || !data[0])
{
Warning( 0,0,"missing WindSpeed argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fWindSpeed = shGetFloat(data);
break;
case eWaveHeight:
if (!data || !data[0])
{
Warning( 0,0,"missing WaveHeight argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fWaveHeight = shGetFloat(data);
break;
case eDirectionalDependence:
if (!data || !data[0])
{
Warning( 0,0,"missing DirectionalDependence argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fDirectionalDependence = shGetFloat(data);
break;
case eChoppyWaveFactor:
if (!data || !data[0])
{
Warning( 0,0,"missing ChoppyWaveFactor argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fChoppyWaveFactor = shGetFloat(data);
break;
case eSuppressSmallWavesFactor:
if (!data || !data[0])
{
Warning( 0,0,"missing SuppressSmallWavesFactor argument for Ocean Effect in Shader '%s'\n", ef->m_Name.c_str());
break;
}
fSuppressSmallWavesFactor = shGetFloat(data);
break;
}
}
PostLoad(4357, fWindDirection, fWindSpeed, fWaveHeight, fDirectionalDependence, fChoppyWaveFactor, fSuppressSmallWavesFactor);
m_CustomTexBind[0] = 0;
#if !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
if (!m_VPs[OVP_NOHEIGHT])
{
m_VPs[OVP_NOHEIGHT] = CVProgram::mfForName("CGVProgOcean_NoHeight");
m_VPs[OVP_NOHEIGHT_SPL] = CVProgram::mfForName("CGVProgOcean_NoHeight_Splash");
m_VPs[OVP_HEIGHT] = CVProgram::mfForName("CGVProgOcean");
m_VPs[OVP_HEIGHT_SPL] = CVProgram::mfForName("CGVProgOcean_Splash");
}
if (!m_VPQ)
m_VPQ = CVProgram::mfForName("CGVProgOcean_SL");
#endif
return true;
}

View File

@@ -0,0 +1,471 @@
#ifndef _CREOCEAN_H_
#define _CREOCEAN_H_
#include "../nvTriStrip/nvTriStrip.h"
struct SREOceanStats
{
float m_StatsTimeFFTTable;
float m_StatsTimeFFT;
float m_StatsTimeUpdateVerts;
float m_StatsTimeTexUpdate;
float m_StatsTimeRendOcean;
int m_StatsAllocatedSectors;
int m_StatsNumRendOceanSectors;
};
#define OCEANPI 3.141592654f
#define OCEANGRID 64
#define LOG_OCEANGRID 6
#define NUM_LODS 5
#define LOD_MASK 7
#define LOD_LEFTSHIFT 3
#define LOD_RIGHTSHIFT 4
#define LOD_TOPSHIFT 5
#define LOD_BOTTOMSHIFT 6
#define OSF_VISIBLE 1
#define OSF_FIRSTTIME 2
#define OSF_NEEDHEIGHTS 4
#define OSF_LODUPDATED 8
#define OSF_BLEND 0x10
#define OVP_NOHEIGHT 0
#define OVP_NOHEIGHT_SPL 1
#define OVP_HEIGHT 2
#define OVP_HEIGHT_SPL 3
#define NUM_OVP 4
#define NUM_OCEANVBS 8
struct SOceanSector
{
float x, y;
int RenderState;
int nLod;
int m_Frame;
int m_Flags;
SOceanSector ()
{
m_Flags = OSF_FIRSTTIME;
m_Frame = -1;
}
};
struct SOceanIndicies
{
float m_fLastAccess;
int m_nInds;
ushort *m_pIndicies;
TArray<SPrimitiveGroup> m_Groups;
};
/**
* A random number class. It implements the <em>mersenne twister</em> algorithm to produce
* "high quality" pseudo random numbers.
*/
class CRERandom
{
public:
enum EMersenneTwisterInitialSeed
{
INITIAL_SEED = 4357U
};
public:
CRERandom( unsigned long ulSeed = INITIAL_SEED ) : m_ulIndex( 0 )
{
SetSeed( ulSeed );
}
~CRERandom() {};
void SetSeed( unsigned long ulSeed )
{
m_ulState[ 0 ] = ( ulSeed | 1 ) & 0xFFFFFFFFU;
for( m_ulIndex = 1; m_ulIndex < N; ++m_ulIndex )
{
m_ulState[ m_ulIndex ] = ( m_ulState[ m_ulIndex - 1 ] * GENERATOR ) & 0xFFFFFFFFU;
}
}
unsigned long GetInteger()
{
if( N == m_ulIndex )
{
Reload();
}
unsigned long ulY = m_ulState[ m_ulIndex++ ];
ulY ^= TemperingShiftU( ulY );
ulY ^= TemperingShiftS( ulY ) & TEMPERING_MASK_B;
ulY ^= TemperingShiftT( ulY ) & TEMPERING_MASK_C;
ulY ^= TemperingShiftL( ulY );
return( ulY );
}
double Get()
{
return( GetInteger() * (double) 2.3283064365386963e-10 ); // i.e. GetInteger() / 2^32
}
double GetInRange( double dLower = 0.0, double dUpper = 1.0 )
{
return( dLower + Get() * ( dUpper - dLower ) );
}
double GetGauss( double dMean = 0.0, double dStdDeviation = 1.0 )
{
double dX1;
double dX2;
double dW;
// perform box muller test
do
{
dX1 = 2.0 * Get() - 1.0;
dX2 = 2.0 * Get() - 1.0;
dW = dX1 * dX1 + dX2 * dX2;
} while( dW >= 1.0 );
dW = sqrt_tpl( -2.0f * log_tpl( dW ) / dW );
dX1 *= dW;
return( dMean + dX1 * dStdDeviation );
}
private:
enum EMersenneTwisterConstants
{
GENERATOR = 69069U,
N = 624U,
M = 397U,
MATRIX_A = 0x9908B0DFU,
UPPER_MASK = 0x80000000U,
LOWER_MASK = 0x7FFFFFFFU,
TEMPERING_MASK_B = 0x9D2C5680U,
TEMPERING_MASK_C = 0xEFC60000U
};
void Reload()
{
const unsigned long c_ulMag01[ 2 ] = { 0x0, MATRIX_A };
unsigned long ulY;
for( m_ulIndex = 0; m_ulIndex < N - M; ++m_ulIndex )
{
ulY = ( m_ulState[ m_ulIndex ] & UPPER_MASK ) |
( m_ulState[ m_ulIndex + 1 ] & LOWER_MASK );
m_ulState[ m_ulIndex ] = m_ulState[ m_ulIndex + M ] ^ ( ulY >> 1 ) ^ c_ulMag01[ ulY & 0x1 ];
}
for( ; m_ulIndex < N - 1; ++m_ulIndex)
{
ulY = ( m_ulState[ m_ulIndex ] & UPPER_MASK ) |
( m_ulState[ m_ulIndex + 1 ] & LOWER_MASK );
m_ulState[ m_ulIndex ] = m_ulState[ m_ulIndex + ( M - N ) ] ^ ( ulY >> 1 ) ^ c_ulMag01[ ulY & 0x1 ];
}
ulY = ( m_ulState[ N - 1 ] & UPPER_MASK ) | ( m_ulState[ 0 ] & LOWER_MASK );
m_ulState[ N - 1 ] = m_ulState[ M - 1 ] ^ ( ulY >> 1 ) ^ c_ulMag01[ ulY & 0x1 ];
m_ulIndex = 0;
}
unsigned long TemperingShiftU( unsigned long ulX )
{
return( ulX >> 11 );
}
unsigned long TemperingShiftS( unsigned long ulX )
{
return( ulX << 7 );
}
unsigned long TemperingShiftT( unsigned long ulX )
{
return( ulX << 15 );
}
unsigned long TemperingShiftL( unsigned long ulX )
{
return( ulX >> 18 );
}
private:
unsigned long m_ulIndex;
unsigned long m_ulState[ N ];
};
//=============================================================================
class CREOcean : public CRendElement
{
friend class CRender3D;
friend class CGLRenderer;
friend class CD3D9Renderer;
public:
static CREOcean *m_pStaticOcean;
CREOcean()
{
m_nFrameLoad = 0;
m_pBuffer = NULL;
mfSetType(eDATA_Ocean);
mfUpdateFlags(FCEF_TRANSFORM);
GenerateGeometry();
m_pStaticOcean = this;
}
virtual ~CREOcean();
public:
void GenerateGeometry();
void GenerateIndices(int nLodCode);
void DrawOceanSector(SOceanIndicies *oi);
void SmoothLods_r(SOceanSector *os, float fSize, int minLod);
void LinkVisSectors(float fSize);
float GetWaterZElevation(float fX, float fY);
void PostLoad( unsigned long ulSeed, float fWindDirection, float fWindSpeed, float fWaveHeight, float fDirectionalDependence, float fChoppyWavesFactor, float fSuppressSmallWavesFactor );
void Update( float fTime );
void UpdateTexture(void);
void PrepareHMap();
private:
int m_nFrameLoad;
float m_fGravity;
float m_fDepth;
TArray <unsigned short> m_pIndices[NUM_LODS];
private:
float *mfFillAdditionalBuffer(SOceanSector *os, int nSplashes, SSplash *pSplashes[], int& nCurSize, int nLod, float fSize);
void FFT(int iDir, float* real, float* imag);
void FFT2DReal(float cmpX[OCEANGRID][OCEANGRID]);
void FFT2D(int iDir, float cmpX[OCEANGRID][OCEANGRID], float cmpY[OCEANGRID][OCEANGRID] );
_inline float sqrf( float x )
{
return (x * x);
}
_inline float PhillipsSpectrum( float fKx, float fKy )
{
float fKLength = cry_sqrtf(sqrf(fKx) + sqrf(fKy));
if( fKLength < 1e-8f )
fKLength = 1e-8f;
float fScale = 1.0f / fKLength;
fKx *= fScale;
fKy *= fScale;
return (m_fWaveHeight * cry_expf(-1.0f / sqrf(fKLength * m_fLargestPossibleWave) - sqrf(fKLength * m_fSuppressSmallWaves)) * cry_powf(fKx*m_fWindX + fKy*m_fWindY, m_fDirectionalDependence) / cry_powf(fKLength, 4.0f));
}
_inline int GetHash(float x, float y)
{
return (int)(x*0.133f+y*0.356f) & 255;
}
_inline SOceanSector *GetSectorByPos(float x, float y, bool bCreate=true)
{
int i;
int hash = GetHash(x, y);
for (i=0; i<m_OceanSectorsHash[hash].Num(); i++)
{
SOceanSector *os = &m_OceanSectorsHash[hash][i];
if (os->x == x && os->y == y)
return os;
}
m_RS.m_StatsAllocatedSectors++;
SOceanSector os;
os.x = x;
os.y = y;
os.m_Flags |= OSF_FIRSTTIME;
os.nLod = NUM_LODS-1;
int n = m_OceanSectorsHash[hash].Num();
m_OceanSectorsHash[hash].AddElem(os);
return &m_OceanSectorsHash[hash][n];
}
int GetLOD(Vec3d camera, Vec3d pos);
private:
TArray<SOceanSector> m_OceanSectorsHash[256];
SOceanIndicies *m_OceanIndicies[1<<(LOD_BOTTOMSHIFT+1)];
TArray<SOceanSector *> m_VisOceanSectors;
float m_fSectorSize;
TArray<unsigned short> m_DWQIndices;
TArray<struct_VERTEX_FORMAT_P3F_COL4UB> m_DWQVertices;
float m_H0X[OCEANGRID+1][OCEANGRID+1];
float m_H0Y[OCEANGRID+1][OCEANGRID+1];
//static _declspec(align(16)) float m_HX[OCEANGRID][OCEANGRID];
//static _declspec(align(16)) float m_HY[OCEANGRID][OCEANGRID];
//static _declspec(align(16)) float m_NX[OCEANGRID][OCEANGRID];
//static _declspec(align(16)) float m_NY[OCEANGRID][OCEANGRID];
//static _declspec(align(16)) float m_DX[OCEANGRID][OCEANGRID];
//static _declspec(align(16)) float m_DY[OCEANGRID][OCEANGRID];
DEFINE_ALIGNED_DATA_STATIC( float, m_HX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA_STATIC( float, m_HY[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA_STATIC( float, m_NX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA_STATIC( float, m_NY[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA_STATIC( float, m_DX[OCEANGRID][OCEANGRID], 16 );
DEFINE_ALIGNED_DATA_STATIC( float, m_DY[OCEANGRID][OCEANGRID], 16 );
vec2_t m_Pos[OCEANGRID+1][OCEANGRID+1];
Vec3d m_Normals[OCEANGRID+1][OCEANGRID+1];
float m_aAngularFreq[OCEANGRID][OCEANGRID];
float m_aKScale[OCEANGRID][OCEANGRID];
float m_fWindX;
float m_fWindY;
float m_fWindSpeed;
float m_fSpeed;
float m_fLargestPossibleWave;
float m_fSuppressSmallWaves;
float m_fWaveHeight;
float m_fDirectionalDependence;
float m_fChoppyWaveFactor;
float m_fSuppressSmallWavesFactor;
CVertexBuffer *m_pBuffer;
Vec3d m_MinBound;
Vec3d m_MaxBound;
//===========================================================================
_inline float GetHMap(float x, float y)
{
float dDownLandZ;
if( x<-m_fExpandHM || y<-m_fExpandHM || x>=m_fTerrainSize+m_fExpandHM || y>=m_fTerrainSize+m_fExpandHM)
dDownLandZ = 0;
else
{
// convert into hmap space
x *= m_fInvHMUnitSize;
y *= m_fInvHMUnitSize;
x += m_fExpandHMap;
y += m_fExpandHMap;
long nX = QInt(x);
long nY = QInt(y);
long nX1 = (nX+1 >= m_nHMapSize) ? nX : nX+1;
long nY1 = (nY+1 >= m_nHMapSize) ? nY : nY+1;
float dx = x - nX;
float dy = y - nY;
float dDownLandZ0 = (1.0f-dx) * m_HMap[nX*m_nHMapSize+nY] + dx * m_HMap[nX1*m_nHMapSize+nY];
float dDownLandZ1 = (1.0f-dx) * m_HMap[nX*m_nHMapSize+nY1] + dx * m_HMap[nX1*m_nHMapSize+nY1];
dDownLandZ = (1-dy) * dDownLandZ0 + dy * dDownLandZ1;
}
return dDownLandZ;
}
public:
#if !defined(PS2) && !defined (GC)
CVProgram * m_VPs[NUM_OVP];
CVProgram * m_VPQ;
#endif
void *m_pVertsPool[NUM_OCEANVBS];
void *m_VertDecl;
void *m_VertDeclHeightSplash;
int m_nCurVB;
int m_nNumVertsInPool;
bool m_bLockedVB;
float *m_HMap;
int m_nHMUnitSize;
float m_fExpandHM;
float m_fExpandHMap;
int m_nHMapSize;
float m_fInvHMUnitSize;
float m_fTerrainSize;
void InitVB();
struct_VERTEX_FORMAT_TEX2F *GetVBPtr(int nVerts);
void UnlockVBPtr();
void mfDrawOceanSectors();
void mfDrawOceanScreenLod();
public:
virtual void mfPrepare();
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
virtual bool mfCompile(SShader *ef, char *scr);
virtual void *mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags);
virtual bool mfPreDraw(SShaderPass *sl);
virtual void mfReset();
virtual int Size()
{
int i;
int nSize = sizeof(*this);
nSize += m_DWQVertices.GetMemoryUsage();
nSize += m_DWQIndices.GetMemoryUsage();
nSize += sizeof(m_Pos);
nSize += sizeof(m_Normals);
nSize += m_VisOceanSectors.GetMemoryUsage() + 12;
for (i=0; i<(1<<(LOD_BOTTOMSHIFT+1)); i++)
{
SOceanIndicies *oi = m_OceanIndicies[i];
if (!oi)
continue;
nSize += sizeof(SOceanIndicies);
nSize += oi->m_nInds * sizeof(short);
nSize += oi->m_Groups.GetMemoryUsage();
}
for (i=0; i<256; i++)
{
nSize += m_OceanSectorsHash[i].GetMemoryUsage()+12;
}
// CREOcean::m_HMap array
nSize += m_nHMapSize * m_nHMapSize * sizeof(float);
return nSize;
}
static SREOceanStats m_RS;
#ifdef DEBUGALLOC
#undef new
#endif
void* operator new( size_t Size )
{
void *ptr = malloc(Size);
memset(ptr, 0, Size);
return ptr;
}
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
};
#endif // _CREOCEAN_H_

View File

@@ -0,0 +1,13 @@
#include "RenderPCH.h"
#include "RendElement.h"
void CREOcclusionQuery::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_FirstVertex = 0;
gRenDev->m_RP.m_RendNumVerts = 4;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
#ifndef __CREPARTICLESPRAY_H__
#define __CREPARTICLESPRAY_H__
//=============================================================
struct SParticle
{
SParticle *prev,*next; // LINK
Vec3d pos; // CURRENT POSITION
Vec3d prevPos[8]; // PREVIOUS POSITION
Vec3d realPos; // CURRENT RENDER POSITION
Vec3d dir; // CURRENT DIRECTION WITH SPEED
Vec3d moveDir; // CURRENT CHANGE DIRECTION
int life; // HOW LONG IT WILL LAST
int startLife;
CFColor color; // CURRENT COLOR OF PARTICLE
CFColor prevColor; // LAST COLOR OF PARTICLE
CFColor deltaColor; // CHANGE OF COLOR
bool bSpark;
float curSize;
float deltaSize;
};
//================================================
#define MAX_PART_MOVE_STAGES 4
enum EMoveType
{
eMTWave,
eMTWhirl,
eMTSqueeze,
};
struct SPartMoveStage
{
EMoveType eMoveType;
SWaveForm WaveMove;
};
//================================================
enum EParticleType
{
ePTPoint,
ePTLine,
ePTPolySegs,
ePTPoly,
ePTBeam,
};
enum EParticleCollision
{
ePCollision_None,
ePCollision_True,
ePCollision_Plane
};
struct SParticleInfo
{
// TRANSFORMATION INFO
float yaw, yawVar; // YAW AND VARIATION
float pitch, pitchVar; // PITCH AND VARIATION
float speed,speedVar;
int life, lifeVar; // LIFE COUNT AND VARIATION
CFColor startColor, startColorVar; // CURRENT COLOR OF PARTICLE
CFColor endColor, endColorVar; // CURRENT COLOR OF PARTICLE
// Physics
Vec3d force;
EParticleType ePT;
int Flags;
// Move info
SPartMoveStage mMoves[MAX_PART_MOVE_STAGES];
int mNumMoves;
Vec3d moveDir;
Vec3d moveDirVar;
// Geometry info
float startSize, startSizeVar;
float endSize, endSizeVar;
float segmOffs;
int segmMax;
int StackSize;
float Squeeze;
};
struct SEmitter
{
SParticleInfo pi;
Vec3d startPos; // XYZ POSITION
Vec3d startPosVar; // XYZ POSITION VARIATION
// Particle
SParticle *particle; // NULL TERMINATED LINKED LIST
int totalParticles[2]; // TOTAL EMITTED AT ANY TIME
int particleCount[2]; // TOTAL EMITTED RIGHT NOW
int emitsPerFrame, emitVar; // EMITS PER FRAME AND VARIATION
EParticleCollision eCollisionType;
Vec3d PlaneAxis;
Vec3d PlaneOffs;
SParticleInfo Spark;
int NumSparks;
float Life;
};
///////////////////////////////////////////////////////////////////////////////
/// Particle Definitions //////////////////////////////////////////////////////
#define MAX_PARTICLES 4096 // MAXIMUM NUMBER OF PARTICLES
///////////////////////////////////////////////////////////////////////////////
#define FP_ANTIALIAS 0x1
struct SParticleStat
{
int NumSprays;
int NumRendSprays;
int NumParticles;
int NumVerts;
int NumIndices;
};
class CREParticleSpray : public CRendElement
{
public:
SEmitter mEmitter;
SParticle *mParticlePool[2];
SParticle *mParticlePntr[2];
int mFrame;
private:
/// Support Function Definitions //////////////////////////////////////////////
bool mfInitParticleSystem();
bool mfSetDefaultEmitter(SEmitter *emitter);
bool mfInitEmitter(SEmitter *emitter);
bool mfAddParticle(SEmitter *emitter, SParticleInfo *pi);
bool mfUpdateParticle(SParticle *particle,SEmitter *emitter);
void mfEmitSparks(SParticle *p, SEmitter *em);
bool mfUpdateEmitter(SEmitter *emitter); // DRAW THE SYSTEM FOR A FRAME
SEmitter *mfGetEmitter(void) { return &mEmitter; }
// Parsing
void mfCompileParticleInfo(SShader *ef, SParticleInfo *pi, char *scr);
void mfCompileCollision(SShader *ef, SEmitter *em, char *scr, char *Collision);
bool mfCompileMove(SShader *ef, SPartMoveStage *pm, SParticleInfo *pi, char *scr);
bool mfCompileMoveTypeSqueeze(SShader *ef, SPartMoveStage *pm, char *scr);
bool mfCompileMoveTypeWhirl(SShader *ef, SPartMoveStage *pm, char *scr);
bool mfCompileMoveTypeWave(SShader *ef, SPartMoveStage *pm, char *scr);
public:
CREParticleSpray()
{
mfSetType(eDATA_ParticleSpray);
mfUpdateFlags(FCEF_TRANSFORM | FCEF_NEEDFILLBUF);
mfInitEmitter(&mEmitter);
}
virtual ~CREParticleSpray();
//CREParticleSpray(CREParticleSpray *Orig);
CREParticleSpray& operator = (const CREParticleSpray& src);
// CRendElement interface
virtual void mfPrepare();
virtual bool mfCull(CCObject *obj);
virtual CRendElement *mfCopyConstruct(void)
{
//CREParticleSpray *ps = new CREParticleSpray;
//*ps = this;
return this;
}
virtual bool mfIsValidTime(SShader *ef, CCObject *obj, float curtime);
virtual bool mfCompile(SShader *ef, char *scr);
static SParticleStat mRS;
static void mfPrintStat();
#ifdef DEBUGALLOC
#undef new
#endif
void* operator new( size_t Size )
{
void *ptr = malloc(Size);
memset(ptr, 0, Size);
return ptr;
}
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
};
#endif // __RENDELEMENT_H__

View File

@@ -0,0 +1,651 @@
/*=============================================================================
CPolyBlend.cpp : implementation of blended polygons RE.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
//===============================================================
bool CREPolyBlend::mfCull(CCObject *obj)
{
CREPolyBlend::mRS.NumPolys++;
if ((obj->m_ObjFlags & FOB_NEAREST))
return false;
return false;
}
bool CREPolyBlend_Base::mfPrepareRB(CCObject *obj, Vec3d& orgo, CFColor& col)
{
if (obj->m_ObjFlags & FOB_DRSUN)
{
orgo = gRenDev->m_RP.m_ViewOrg + 2000.0f * gRenDev->m_RP.m_SunDir;
}
/*else
if (obj->m_ObjFlags & FOB_DRPLANET)
{
orgo = obj->m_Trans + gRenDev->m_RP.m_ViewOrg;
orgo[2] += 2000;
}*/
else
{
orgo = obj->GetTranslation();
}
col = obj->m_Color;
if (col[0]+col[1]+col[2] == 0)
col = CFColor(1.0f);
if (obj->m_ObjFlags & FOB_DRSUN)
{
CREFlareGeom *fl = (CREFlareGeom *)obj->m_RE;
fl->mfCheckVis(col, obj);
if (!col.a)
return false; // Flare not visible
col.ScaleCol(col.a);
col.a = 1;
}
else
if (eColStyle || eAlphaStyle)
{
float frac;
if (eColStyle)
{
col = Col_White;
if (eColStyle == ePBCS_Decay)
{
frac = (gRenDev->m_RP.m_RealTime-obj->m_StartTime)/LiveTime;
col.ScaleCol(frac);
}
}
if (eAlphaStyle)
{
if (eAlphaStyle == ePBCS_Decay)
{
if (obj->m_StartTime+LiveTimeA < gRenDev->m_RP.m_RealTime-0.001)
frac = 1;
else
frac = (gRenDev->m_RP.m_RealTime-obj->m_StartTime)/LiveTimeA;
col[3] = ValA0 + frac * (ValA1-ValA0);
}
}
}
else
{
CLightStyle *ls = CLightStyle::m_LStyles[obj->m_LightStyle];
ls->mfUpdate(gRenDev->m_RP.m_RealTime);
col = ls->m_Color;
col[3] = 1.0f;
}
return true;
}
void CREPolyBlend_Base::mfSetVerts(CCObject *obj, Vec3d& orgo, uint c, SOrient *ori)
{
Vec3d VecX, VecY, v;
Vec3d org;
float distX, distY;
float *verts[4];
Vec3d norm;
bvec4 *cols;
int i;
static int inds[] = {3, 0, 2, 2, 0, 1};
static float tverts[4][2] =
{
{0, 0},
{1, 0},
{1, 1},
{0, 1}
};
int n = gRenDev->m_RP.m_RendNumVerts;
byte *p = gRenDev->m_RP.m_Ptr.PtrB + n*gRenDev->m_RP.m_Stride;
verts[0] = (float *)p;
p += gRenDev->m_RP.m_Stride;
verts[1] = (float *)p;
p += gRenDev->m_RP.m_Stride;
verts[2] = (float *)p;
p += gRenDev->m_RP.m_Stride;
verts[3] = (float *)p;
org = orgo;
if (ori->m_Flags & FOR_ORTHO)
{
VecX = gRenDev->m_RP.m_CamVecs[1];
VecY = gRenDev->m_RP.m_CamVecs[2];
org += ori->m_Coord.m_Org;
v = org - gRenDev->m_RP.m_ViewOrg;
distX = v.GetLength();
norm = -gRenDev->m_RP.m_CamVecs[0];
}
else
{
VecX = ori->m_Coord.m_Vecs[1];
VecY = ori->m_Coord.m_Vecs[2];
org += ori->m_Coord.m_Org;
v = org - gRenDev->m_RP.m_ViewOrg;
distX = v.GetLength();
norm = -ori->m_Coord.m_Vecs[0];
}
if (gRenDev->m_RP.m_PersFlags & RBPF_DRAWMIRROR)
{
VecY = -VecY;
}
distY = distX;
if (ScaleX > 0)
{
distX = ScaleX;
distY = ScaleY;
}
else
if (ScaleX < 0)
{
distX *= -ScaleX * 0.1f;
distY *= -ScaleY * 0.1f;
}
else
distX = distY = 10.0f;
VecX *= distX;
VecY *= distY;
verts[0][0] = org[0]+VecX[0]+VecY[0];
verts[0][1] = org[1]+VecX[1]+VecY[1];
verts[0][2] = org[2]+VecX[2]+VecY[2];
verts[1][0] = org[0]-VecX[0]+VecY[0];
verts[1][1] = org[1]-VecX[1]+VecY[1];
verts[1][2] = org[2]-VecX[2]+VecY[2];
verts[2][0] = org[0]-VecX[0]-VecY[0];
verts[2][1] = org[1]-VecX[1]-VecY[1];
verts[2][2] = org[2]-VecX[2]-VecY[2];
verts[3][0] = org[0]+VecX[0]-VecY[0];
verts[3][1] = org[1]+VecX[1]-VecY[1];
verts[3][2] = org[2]+VecX[2]-VecY[2];
UPipeVertex ptr = gRenDev->m_RP.m_NextPtr;
byte *OffsT, *OffsD;
SMRendTexVert *rtvb;
byte *OffsN;
switch (gRenDev->m_RP.m_FT)
{
case FLT_BASE:
cols = &gRenDev->m_RP.m_pClientColors[n];
OffsT = gRenDev->m_RP.m_OffsT + ptr.PtrB;
for (i=0; i<4; i++, cols++, OffsT+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsT) = tverts[i][0];
*(float *)(OffsT+4) = tverts[i][1];
*(uint *)cols = c;
}
break;
case FLT_BASE + FLT_COL:
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
OffsT = gRenDev->m_RP.m_OffsT + ptr.PtrB;
for (i=0; i<4; i++, OffsT+=gRenDev->m_RP.m_Stride, OffsD+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsT) = tverts[i][0];
*(float *)(OffsT+4) = tverts[i][1];
*(uint *)OffsD = c;
}
break;
case FLT_COL:
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
for (i=0; i<4; i++, OffsD+=gRenDev->m_RP.m_Stride)
{
*(uint *)OffsD = c;
}
break;
case FLT_COL + FLT_SYSBASE:
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<4; i++, OffsD+=gRenDev->m_RP.m_Stride)
{
Vector2Copy(tverts[i], rtvb[i].vert);
*(uint *)OffsD = c;
}
break;
case 0:
cols = &gRenDev->m_RP.m_pClientColors[n];
for (i=0; i<4; i++, cols++)
{
*(uint *)cols = c;
}
break;
case FLT_SYSBASE:
cols = &gRenDev->m_RP.m_pClientColors[n];
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<4; i++, cols++)
{
Vector2Copy(tverts[i], rtvb[i].vert);
*(uint *)cols = c;
}
break;
case FLT_BASE + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
cols = &gRenDev->m_RP.m_pClientColors[n];
OffsT = gRenDev->m_RP.m_OffsT + ptr.PtrB;
for (i=0; i<4; i++, cols++, OffsT+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
*(float *)(OffsT) = tverts[i][0];
*(float *)(OffsT+4) = tverts[i][1];
*(uint *)cols = c;
}
break;
case FLT_BASE + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
OffsT = gRenDev->m_RP.m_OffsT + ptr.PtrB;
for (i=0; i<4; i++, OffsT+=gRenDev->m_RP.m_Stride, OffsD+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
*(float *)(OffsT) = tverts[i][0];
*(float *)(OffsT+4) = tverts[i][1];
*(uint *)OffsD = c;
}
break;
case FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
for (i=0; i<4; i++, OffsD+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
*(uint *)OffsD = c;
}
break;
case FLT_COL + FLT_SYSBASE + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
OffsD = gRenDev->m_RP.m_OffsD + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<4; i++, OffsD+=gRenDev->m_RP.m_Stride)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
Vector2Copy(tverts[i], rtvb[i].vert);
*(uint *)OffsD = c;
}
break;
case 0 + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
cols = &gRenDev->m_RP.m_pClientColors[n];
for (i=0; i<4; i++, cols++)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
*(uint *)cols = c;
}
break;
case FLT_SYSBASE + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
cols = &gRenDev->m_RP.m_pClientColors[n];
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<4; i++, cols++)
{
*(float *)(OffsN) = norm.x;
*(float *)(OffsN+4) = norm.y;
*(float *)(OffsN+8) = norm.z;
Vector2Copy(tverts[i], rtvb[i].vert);
*(uint *)cols = c;
}
break;
default:
break;
}
if ((gRenDev->m_RP.m_FT & FLT_COL) && gbRgb)
{
OffsD = gRenDev->m_RP.m_OffsD + gRenDev->m_RP.m_NextPtr.PtrB;
for (i=0; i<4; i++, OffsD+=gRenDev->m_RP.m_Stride)
{
*(uint *)(OffsD) = COLCONV(*(uint *)(OffsD));
}
}
ptr.PtrB += gRenDev->m_RP.m_Stride*4;
gRenDev->m_RP.m_NextPtr = ptr;
ushort *dinds = &gRenDev->m_RP.m_RendIndices[gRenDev->m_RP.m_RendNumIndices];
for (i=0; i<6; i++)
{
*dinds++ = inds[i]+n;
}
}
void CREPolyBlend::mfPrepare(void)
{
CCObject *obj = gRenDev->m_RP.m_pCurObject;
if (!obj)
return;
int savev = gRenDev->m_RP.m_RendNumVerts;
int savei = gRenDev->m_RP.m_RendNumIndices;
CREPolyBlend::mRS.NumRendPolys++;
SShader *ef = gRenDev->m_RP.m_pShader;
CFColor col;
Vec3d orgo;
if (!mfPrepareRB(obj, orgo, col))
return;
uint c = col.GetTrue();
for (int o=0; o<NumOrients; o++)
{
gRenDev->EF_CheckOverflow(4, 6, this);
mfSetVerts(obj, orgo, c, Orients[o]);
gRenDev->m_RP.m_RendNumVerts += 4;
gRenDev->m_RP.m_RendNumIndices += 6;
}
CREPolyBlend::mRS.NumVerts += gRenDev->m_RP.m_RendNumVerts - savev;
CREPolyBlend::mRS.NumIndices += gRenDev->m_RP.m_RendNumIndices - savei;
}
//=====================================================================
bool CREAnimPolyBlend::mfCull(CCObject *obj)
{
CREPolyBlend::mRS.NumAnimPolys++;
//if(gfCullSphere(obj->m_Trans, 100)==2)
// return true;
return false;
}
bool CREPolyBlend::mfIsValidTime(SShader *ef, CCObject *obj, float curtime)
{
if (!LiveTime)
return true;
if (curtime > LiveTime+obj->m_StartTime)
return false;
return true;
}
bool CREAnimPolyBlend::mfIsValidTime(SShader *ef, CCObject *obj, float curtime)
{
int i, j;
SShaderTexUnit *shm;
SShaderPass *sfm;
for (i=0; i<ef->m_Passes.Num(); i++)
{
sfm = &ef->m_Passes[i];
for (j=0; j<sfm->m_TUnits.Num(); j++)
{
shm = &sfm->m_TUnits[j];
if (!shm->m_AnimInfo)
continue;
if (shm->m_AnimInfo->m_Time && shm->m_AnimInfo->m_TexPics.Num())
{
float t = curtime - obj->m_StartTime;
int m = (int)(t / shm->m_AnimInfo->m_Time);
if (m >= shm->m_AnimInfo->m_TexPics.Num())
return false;
}
}
}
return true;
}
void CREAnimPolyBlend::mfPrepare(void)
{
CCObject *obj = gRenDev->m_RP.m_pCurObject;
if (!obj)
return;
int savev = gRenDev->m_RP.m_RendNumVerts;
int savei = gRenDev->m_RP.m_RendNumIndices;
CREPolyBlend::mRS.NumRendPolys++;
SShader *ef = gRenDev->m_RP.m_pShader;
CFColor col;
Vec3d orgo;
if (!mfPrepareRB(obj, orgo, col))
return;
uint c = col.GetTrue();
for (int o=0; o<NumOrients; o++)
{
gRenDev->EF_CheckOverflow(4, 6, this);
mfSetVerts(obj, orgo, c, Orients[o]);
gRenDev->m_RP.m_RendNumVerts += 4;
gRenDev->m_RP.m_RendNumIndices += 6;
}
CREPolyBlend::mRS.NumVerts += gRenDev->m_RP.m_RendNumVerts - savev;
CREPolyBlend::mRS.NumIndices += gRenDev->m_RP.m_RendNumIndices - savei;
}
//=======================================================================
SPolyBlendStat CREPolyBlend::mRS;
void CREPolyBlend::mfPrintStat()
{
/* char str[1024];
*gpCurPrX = 4;
sprintf(str, "Num Indices: %i\n", mRS.NumIndices);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Verts: %i\n", mRS.NumVerts);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Render AnimPolys: %i\n", mRS.NumAnimRendPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Occluding AnimPolys: %i\n", mRS.NumAnimPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Render Polys: %i\n", mRS.NumRendPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Occluding Polys: %i\n", mRS.NumPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
gRenDev->mfPrintString ("\nBlended Polygons status info:\n", PS_TRANSPARENT | PS_UP);*/
}
//===================================================================================================
// Parsing
void CREPolyBlend_Base::mfCompileOrients(SShader *ef, int *nums, SOrient *Orients[], char *scr)
{
if (!scr || !scr[0])
{
Warning( 0,0,"Can't declare orient for effector '%s'\n", ef->m_Name.c_str());
*nums = 1;
Orients[0] = &gRenDev->m_cEF.m_Orients[0];
}
else
{
int ors[16];
*nums = sscanf(scr, "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", &ors[0], &ors[1], &ors[2], &ors[3], &ors[4], &ors[5], &ors[6], &ors[7], &ors[8], &ors[9], &ors[10], &ors[11], &ors[12], &ors[13], &ors[14], &ors[15]);
if (!(*nums))
{
Warning( 0,0,"Can't declare orient for effector '%s'\n", ef->m_Name.c_str());
*nums = 1;
Orients[0] = &gRenDev->m_cEF.m_Orients[0];
}
else
{
for (int i=0; i<*nums; i++)
{
if (ors[i] >= gRenDev->m_cEF.m_NumOrients)
{
Warning( 0,0,"Can't declare %d orient (Use Ortho mode)\n", ors[i]);
*nums = 1;
Orients[0] = &gRenDev->m_cEF.m_Orients[0];
return;
}
Orients[i] = &gRenDev->m_cEF.m_Orients[ors[i]];
}
}
}
}
bool CREPolyBlend_Base::mfCompile(SShader *ef, char *scr)
{
char* name;
long cmd;
char *params;
char *data;
enum {eTrace=1, eType, eScale, eScalX, eScalY, eOrients, eRGBStyle, eAlphaStyle};
static tokenDesc commands[] =
{
{eTrace, "Trace"},
{eType, "Type"},
{eScale, "Scale"},
{eScalX, "ScalX"},
{eScalY, "ScalY"},
{eOrients, "Orients"},
{eRGBStyle, "RGBStyle"},
{eAlphaStyle, "AlphaStyle"},
{0,0}
};
while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
{
data = NULL;
if (name)
data = name;
else
if (params)
data = params;
switch (cmd)
{
case eTrace:
mfUpdateFlags(FCEFPB_TRACE);
break;
case eType:
if (!stricmp(data, "Beam"))
this->eType = ePBT_Beam;
else
Warning( 0,0,"unknown Type parameter '%s' in Shader '%s' (CREPolyBlend)\n", data, ef->m_Name.c_str());
break;
case eScale:
ScaleX = ScaleY = shGetFloat(data);
break;
case eScalX:
ScaleX = shGetFloat(data);
break;
case eScalY:
ScaleY = shGetFloat(data);
break;
case eRGBStyle:
if (!stricmp(data, "Decay"))
{
eColStyle = ePBCS_Decay;
if (!params || !params[0])
{
Warning( 0,0,"missing RgbStyle Decay value in Shader '%s' (skipped) (CREPolyBlend)\n", ef->m_Name.c_str());
Val0 = 1;
Val1 = 0;
LiveTime = 1;
}
else
{
sscanf(params, "%f %f %f", &Val0, &Val1, &LiveTime);
}
}
else
Warning( 0,0,"unknown RgbStyle parameter '%s' in Shader '%s' (CREPolyBlend)\n", data, ef->m_Name.c_str());
case eAlphaStyle:
if (!stricmp(data, "Decay"))
{
this->eAlphaStyle = ePBCS_Decay;
if (!params || !params[0])
{
Warning( 0,0,"missing RgbStyle Decay value in Shader '%s' (skipped) (CREPolyBlend)\n", ef->m_Name.c_str());
ValA0 = 1;
ValA1 = 0;
LiveTimeA = 1;
}
else
{
sscanf(params, "%f %f %f", &ValA0, &ValA1, &LiveTimeA);
}
}
else
Warning( 0,0,"unknown RgbStyle parameter '%s' in Shader '%s' (CREPolyBlend)\n", data, ef->m_Name.c_str());
case eOrients:
mfCompileOrients(ef, &NumOrients, Orients, params);
if (Orients[0] == &gRenDev->m_cEF.m_Orients[0])
mfUpdateFlags(FCEFPB_ORTHO);
break;
}
}
return true;
}

View File

@@ -0,0 +1,121 @@
#ifndef __CREPOLYBLEND_H__
#define __CREPOLYBLEND_H__
//=============================================================
#define FCEFPB_TRACE 0x10000
#define FCEFPB_ORTHO 0x20000
#define FCEFPB_SCALE 0x40000
#define FCEFPB_PLANET 0x80000
enum ePBColStyle
{
ePBCS_None,
ePBCS_Decay,
};
enum ePBType
{
ePBT_Sprite,
ePBT_Beam,
};
struct SPolyBlendStat
{
int NumPolys;
int NumRendPolys;
int NumAnimPolys;
int NumAnimRendPolys;
int NumVerts;
int NumIndices;
};
class CREPolyBlend_Base : public CRendElement
{
public:
float ScaleX, ScaleY;
int NumOrients;
SOrient *Orients[16];
ePBColStyle eColStyle;
ePBColStyle eAlphaStyle;
ePBType eType;
float LiveTime;
float LiveTimeA;
float Val0;
float Val1;
float ValA0;
float ValA1;
public:
CREPolyBlend_Base()
{
ScaleX = ScaleY = 0;
eColStyle = ePBCS_None;
eType = ePBT_Sprite;
LiveTime = 0;
}
virtual bool mfCompile(SShader *ef, char *scr);
protected:
bool mfPrepareRB(CCObject *obj, Vec3d& orgo, CFColor& col);
void mfSetVerts(CCObject *obj, Vec3d& orgo, uint c, SOrient *ori);
void mfCompileOrients(SShader *ef, int *nums, SOrient *Orients[], char *scr);
};
class CREPolyBlend : public CREPolyBlend_Base
{
public:
static SPolyBlendStat mRS;
static void mfPrintStat();
public:
CREPolyBlend()
{
mfSetType(eDATA_PolyBlend);
Val0 = Val1 = 0;
mfSetFlags(FCEF_NEEDFILLBUF);
}
virtual ~CREPolyBlend() {};
virtual void mfPrepare();
virtual bool mfCull(CCObject *obj);
virtual CRendElement *mfCopyConstruct(void)
{
CREPolyBlend *pb = new CREPolyBlend;
*pb = *this;
return pb;
}
virtual bool mfIsValidTime(SShader *ef, CCObject *obj, float curtime);
};
class CREAnimPolyBlend : public CREPolyBlend_Base
{
public:
int curNum;
public:
CREAnimPolyBlend() : CREPolyBlend_Base()
{
mfSetType(eDATA_AnimPolyBlend);
mfSetFlags(FCEF_NEEDFILLBUF);
}
virtual ~CREAnimPolyBlend() {};
virtual void mfPrepare();
virtual bool mfCull(CCObject *obj);
virtual CRendElement *mfCopyConstruct(void)
{
CREAnimPolyBlend *apb = new CREAnimPolyBlend;
*apb = *this;
return apb;
}
virtual bool mfIsValidTime(SShader *ef, CCObject *obj, float curtime);
};
#endif // __CREPOLYBLEND_H__

View File

@@ -0,0 +1,485 @@
/*=============================================================================
CREPolyMesh.cpp : implementation of mesh polygons RE.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
#include <CREPolyMesh.h>
//===============================================================
SPolyStat CREPolyMesh::mRS;
CREPolyMesh::~CREPolyMesh()
{
if (TriVerts)
delete [] TriVerts;
if (Indices)
delete [] Indices;
if (bNoDeform)
delete [] bNoDeform;
}
void CREPolyMesh::mfGetPlane(Plane& pl)
{
pl.n = m_Plane.n;
pl.d = m_Plane.d;
}
CRendElement *CREPolyMesh::mfCopyConstruct(void)
{
CREPolyMesh *pm = new CREPolyMesh;
*pm = *this;
return pm;
}
bool CREPolyMesh::mfCullFace(ECull cl)
{
CREPolyMesh::mRS.NumOccPolys++;
if (cl != eCULL_None)
{
float d = m_Plane.n * gRenDev->m_RP.m_ViewOrg;
if (cl == eCULL_Front)
{
if (d < m_Plane.d-8.0f)
return true;
}
else
{
if (d > m_Plane.d+8.0f)
return true;
}
}
CREPolyMesh::mRS.NumRendPolys++;
return false;
}
void CREPolyMesh::mfCenter(Vec3d& centr, CCObject *pObj)
{
int i;
centr(0,0,0);
for (i=0; i<NumVerts; i++)
{
centr += TriVerts[i].vert;
}
float s = 1.0f / NumVerts;
centr *= s;
if (pObj)
centr += pObj->GetTranslation();
}
int CREPolyMesh::mfTransform(Matrix44& ViewMatr, Matrix44& ProjMatr, vec4_t *verts, vec4_t *vertsp, int Num)
{
int i, j;
for (i=0; i<NumVerts; i++)
{
if (i == Num)
break;
for (j=0; j<4; j++)
{
verts[i][j] = TriVerts[i].vert[0]*ViewMatr(0,j) + TriVerts[i].vert[1]*ViewMatr(1,j) + TriVerts[i].vert[2]*ViewMatr(2,j) + ViewMatr(3,j);
}
}
for (i=0; i<NumVerts; i++)
{
if (i == Num)
break;
for (j=0; j<4; j++)
{
vertsp[i][j] = verts[i][0]*ProjMatr(0,j) + verts[i][1]*ProjMatr(1,j) + verts[i][2]*ProjMatr(2,j) + verts[i][3]*ProjMatr(3,j);
}
}
return NumVerts;
}
void CREPolyMesh::mfPrepare(void)
{
ushort *inds;
int i, n;
SShader *ef = gRenDev->m_RP.m_pShader;
CREPolyMesh::mRS.NumVerts += NumVerts;
CREPolyMesh::mRS.NumIndices += NumIndices;
// Check overflow
gRenDev->EF_CheckOverflow(NumVerts, NumIndices, this);
inds = Indices;
n = gRenDev->m_RP.m_RendNumVerts;
#ifdef OPENGL
ushort *dinds = &gRenDev->m_RP.m_RendIndices[gRenDev->m_RP.m_RendNumIndices];
#else
ushort *dinds = &gRenDev->m_RP.m_RendIndices[gRenDev->m_RP.m_RendNumIndices];
#endif
i = NumIndices;
gRenDev->m_RP.m_RendNumIndices += i;
while(i--)
{
*dinds++ = *inds++ + n;
}
UPipeVertex ptr = gRenDev->m_RP.m_NextPtr;
//SMRendTexVert *rtvb, *rtvl;
SMTriVert *tv = TriVerts;
//byte *OffsN;
int m = NumVerts;
/*switch (gRenDev->m_RP.mFT)
{
case FLT_BASE:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_1T->st);
}
break;
case FLT_BASE + FLT_COL:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_1T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_1T->st);
}
break;
case FLT_SYSBASE:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_SYSBASE + FLT_COL:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_1T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_BASE + FLT_LM:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_2T->st[0]);
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
}
break;
case FLT_BASE + FLT_LM + FLT_COL:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_2T->st[0]);
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
}
break;
case FLT_SYSBASE + FLT_LM:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_SYSBASE + FLT_LM + FLT_COL:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_SYSBASE + FLT_SYSLM:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
rtvl = &gRenDev->m_RP.m_pLMTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++, rtvl++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].lmTC, rtvl->vert);
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_SYSBASE + FLT_SYSLM + FLT_COL:
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
rtvl = &gRenDev->m_RP.m_pLMTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride, rtvb++, rtvl++)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, rtvl->vert);
Vector2Copy(tv[i].dTC, rtvb->vert);
}
break;
case FLT_BASE + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_1T->st);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_BASE + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_1T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_1T->st);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_1T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_BASE + FLT_LM + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_2T->st[0]);
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_BASE + FLT_LM + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].dTC, ptr.Ptr_D_2T->st[0]);
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_LM + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_LM + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_SYSLM + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
rtvl = &gRenDev->m_RP.m_pLMTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
Vector2Copy(tv[i].lmTC, rtvl[i].vert);
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSBASE + FLT_SYSLM + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvb = &gRenDev->m_RP.m_pBaseTexCoordPointer[n];
rtvl = &gRenDev->m_RP.m_pLMTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, rtvl[i].vert);
Vector2Copy(tv[i].dTC, rtvb[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_LM + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, ptr.Ptr_D_2T->st[1]);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_SYSLM + FLT_COL + FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
rtvl = &gRenDev->m_RP.m_pLMTexCoordPointer[n];
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
Vector2Copy(tv[i].lmTC, rtvl[i].vert);
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case FLT_COL:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
ptr.Ptr_D_2T->color.dcolor = -1;
}
break;
case FLT_N:
OffsN = gRenDev->m_RP.m_OffsN + ptr.PtrB;
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
*(float *)(OffsN) = m_Plane.n.x;
*(float *)(OffsN+4) = m_Plane.n.y;
*(float *)(OffsN+8) = m_Plane.n.z;
}
break;
case 0:
for (i=0; i<m; i++, ptr.PtrB+=gRenDev->m_RP.m_Stride)
{
ptr.Ptr_D_1T->xyz = tv[i].vert;
}
break;
default:
break;
}*/
gRenDev->m_RP.m_NextPtr = ptr;
gRenDev->m_RP.m_RendNumVerts += NumVerts;
}
void CREPolyMesh::mfPrintStat()
{
// char str[1024];
/* *gpCurPrX = 4;
sprintf(str, "Num Indices: %i\n", mRS.NumIndices);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Verts: %i\n", mRS.NumVerts);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Rend. Details: %i\n", mRS.NumRendDetails);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Calc. Details: %i\n", mRS.NumDetails);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num Rend Polys: %i\n", mRS.NumRendPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
sprintf(str, "Num BSP Occluded Polys: %i\n", mRS.NumOccPolys);
gRenDev->mfPrintString (str, PS_TRANSPARENT | PS_UP);
*gpCurPrX = 4;
gRenDev->mfPrintString ("\nPolys status info:\n", PS_TRANSPARENT | PS_UP);*/
}

View File

@@ -0,0 +1,76 @@
/*=============================================================================
CREPrefabGeom.cpp : implementation of wall geometry RE for the editor.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#include "RenderPCH.h"
#include "RendElement.h"
//===============================================================
CRendElement *CREPrefabGeom::mfCopyConstruct(void)
{
CREPrefabGeom *cp = new CREPrefabGeom;
*cp = *this;
return cp;
}
bool CREPrefabGeom::mfCompile(SShader *ef, char *scr)
{
char* name;
long cmd;
char *params;
char *data;
enum {eModel=1};
static tokenDesc commands[] =
{
{eModel, "Model"},
{0,0}
};
while ((cmd = shGetObject (&scr, commands, &name, &params)) > 0)
{
data = NULL;
if (name)
data = name;
else
if (params)
data = params;
switch (cmd)
{
case eModel:
mModel = NULL;//(CModelCgf *)CComModel::mfForName(data);
break;
}
}
if (mModel)
return true;
return false;
}
void CREPrefabGeom::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
bool CREPrefabGeom::mfDraw(SShader *ef, SShaderPass *sl)
{
//if (mModel)
// mModel->mfDraw(ef, bCamera);
return true;
}

View File

@@ -0,0 +1,41 @@
#ifndef __CREPREFABGEOM_H__
#define __CREPREFABGEOM_H__
//=============================================================
struct SREPrefabStat
{
int NumRendPolys;
int NumVerts;
int NumIndices;
};
class CModelCgf;
class CREPrefabGeom : public CRendElement
{
public:
void *mModel;
static SREPrefabStat mRS;
static void mfPrintStat();
public:
CREPrefabGeom()
{
mfSetType(eDATA_Prefab);
mModel = 0;
mfSetFlags(FCEF_TRANSFORM);
}
virtual ~CREPrefabGeom() {};
bool mfCullBox(Vec3d vmin, Vec3d vmax);
virtual CRendElement *mfCopyConstruct(void);
virtual bool mfCompile(SShader *ef, char *scr);
virtual void mfPrepare();
virtual bool mfDraw(SShader *ef, SShaderPass *sl);
};
#endif // __CREPREFABGEOM_H__

View File

@@ -0,0 +1,381 @@
/*
=========================================================================
FILE : CRECommon.h
DESC : render elements common stuff
PROJ : Crytek Engine
CODER: Tiago Sousa
NOTE/TODO/FIX:
. All shaders, specialized textures used, should be initialized/destroyed
in CScreenVars class
. All data should be fx/name independent, accessible trought data index
. Give better data organization..
Last Update: 13/10/2003
=========================================================================
*/
#ifndef _CRECOMMON_H_
#define _CRECOMMON_H_
//-------------------------------------------------------------------------------------------------
// screen processing types parameter
enum EProcessType
{
SCREENPROCESS_FADE,
SCREENPROCESS_BLUR,
SCREENPROCESS_COLORTRANSFER,
SCREENPROCESS_CONTRAST,
SCREENPROCESS_MOTIONBLUR,
SCREENPROCESS_GLARE,
SCREENPROCESS_NIGHTVISION,
SCREENPROCESS_HEATVISION,
SCREENPROCESS_FLASHBANG,
SCREENPROCESS_CARTOON,
SCREENPROCESS_DOF,
// special case, to get screen texture, after all post-processing
SCREENPROCESS_SCREENTEX,
};
//-------------------------------------------------------------------------------------------------
// screen processing types parameters
enum EProcessParameter
{
SCREENPROCESS_FADECOLOR,
SCREENPROCESS_BLURAMOUNT,
SCREENPROCESS_BLURCOLORRED,
SCREENPROCESS_BLURCOLORGREEN,
SCREENPROCESS_BLURCOLORBLUE,
SCREENPROCESS_COLORTRANSFERCOLOR,
SCREENPROCESS_COLORTRANSFERAMOUNT,
SCREENPROCESS_CONTRASTAMOUNT,
SCREENPROCESS_MOTIONBLURTYPE,
SCREENPROCESS_MOTIONBLURAMOUNT,
SCREENPROCESS_MOTIONBLURDISPLACE,
SCREENPROCESS_GLAREAMOUNT,
SCREENPROCESS_GLARELUMSIZE,
SCREENPROCESS_GLAREMAXAMOUNT,
SCREENPROCESS_GLAREBOXSIZE,
SCREENPROCESS_GLARETHRESHOLD,
SCREENPROCESS_NIGHTVISIONCOLORRED,
SCREENPROCESS_NIGHTVISIONCOLORGREEN,
SCREENPROCESS_NIGHTVISIONCOLORBLUE,
SCREENPROCESS_FLASHBANGTIMESCALE,
SCREENPROCESS_FLASHBANGFLASHPOSX,
SCREENPROCESS_FLASHBANGFLASHPOSY,
SCREENPROCESS_FLASHBANGFLASHSIZEX,
SCREENPROCESS_FLASHBANGFLASHSIZEY,
SCREENPROCESS_FLASHBANGTIMEOUT,
SCREENPROCESS_FLASHBANGFORCEAFTERIMAGE,
SCREENPROCESS_DOFFOCALDISTANCE,
SCREENPROCESS_DOFBLURAMOUNT,
SCREENPROCESS_TRANSITIONTIME,
SCREENPROCESS_PRETRANSITIONTIME,
SCREENPROCESS_ACTIVE
};
#define SHADERSCHECK !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
//-------------------------------------------------------------------------------------------------
// screen processing vars class
class CScreenVars
{
public:
CScreenVars()
{
// initialize members
// set shaders to null...
m_pRCColorTransfer=0;
m_pVPColorTransfer=0;
m_pRCMotion=0;
m_pRCMotionAmount=0;
m_pVPMotion=0;
m_pRCBluryScreen=0;
m_pVPBluryScreen=0;
m_pRCGlareMap=0;
m_pRCGlareAmountMap=0;
m_pRCGlare=0;
m_pRCRenderModeCold=0;
m_pRCRenderModeAdv=0;
m_pVPGlare=0;
m_pRCNightVision=0;
m_pVPNightVision=0;
m_pRCHeatVision=0;
m_pRCHeatSourceDecode=0;
m_pRCFlashBang=0;
m_pVPFlashBang=0;
m_pRCFlashBang=0;
m_pVPFlashBang=0;
m_pRCBlur=0;
m_pVPBlur=0;
m_pRCReplRgbToAlpha=0;
m_pVPCartoon=0;
m_pRCCartoon=0;
m_pRCCartoonSilhouette=0;
m_pRCDof=0;
// fade process vars
m_bFadeActive=0;
m_fFadeTime=0;
m_fFadePreTime=0;
m_fFadeCurrPreTime=0;
m_fFadeCurrTime=0;
m_pFadeColor.set(0,0,0,0);
m_pFadeCurrColor.set(0,0,0,0);
// color transfer vars
m_bColorTransferActive=0;
m_pColorTransferColor.set(0,0,0,0);
m_fColorTransferAmount=1;
// motion blur vars
m_bMotionBlurActive=0;
m_fMotionBlurAmount=0.9f;
m_iMotionBlurType=1;
m_iMotionBlurDisplace=0;
// blury screen vars
m_bBlurActive=0;
m_fBlurAmount=1.0f;
m_pBlurColor.set(1,1,1,1);
// glare vars
m_bGlareActive=0;
m_fGlareThreshold=75;
m_iGlareBox=2;
m_iGlareLumSize=2;
m_iGlareSize=128;
m_fGlareAmount=1.0f;
m_fGlareAmountDynamic=1.0f;
m_fGlareMaxAmount=4.0f;
m_pCurrGlareMapConst.set(0.2f, 0.2f, 0.2f, 1.0f);
m_pCurrSaturation.set(0.0f, 0.0f, 0.0f, 0.2f);
m_pCurrContrast.set(0.0f, 0.0f, 0.85f, 0.15f);
// nightvision vars
m_iNightVisionActive=0;
m_pNightVisionColor.set(-0.1f, 0.2f, 0.11f, 1.0f);
// heatvision vars
m_iHeatVisionActive=0;
m_pCVHeatVision=0;
// flashbang vars
m_bFlashBangActive=0;
m_iFlashBangForce=0;
m_fFlashBangTimeScale=1.0f;
m_fFlashBangTimeOut=1.0f;
m_fFlashBangFlashPosX=200;
m_fFlashBangFlashPosY=100;
m_fFlashBangFlashSizeX=400;
m_fFlashBangFlashSizeY=400;
// cartoon vars
m_bCartoonActive=0;
// depth of field vars
m_bDofActive=0;
m_fDofFocalDistance=0;
// screentex vars
m_bScreenTexActive=0;
// console vars
m_pCVDisableSfx=0; //GET_CVAR("r_DisableSfx");
m_pCVResetSfx=0; //GET_CVAR("r_ResetScreenFx");
m_pCVNormalGlare=0; //GET_CVAR("r_Glare");
m_pCVMotionBlur=0; //GET_CVAR("r_MotionBlur");
m_pCVScreenColorTransfer=0; //GET_CVAR("r_ScreenColorTransfer");
m_pCVMotionBlurAmount=0; //GET_CVAR("r_MotionBlurAmount");
m_pCVMotionBlurDisplace=0; //GET_CVAR("r_MotionBlurDisplace");
m_pCVRenderMode=0; //GET_CVAR("r_RenderMode");
// note: these are used for correct cryvision functioning
m_pCVStencilShadows=0; //GET_CVAR("e_stencil_shadows")
m_iPrevStencilShadows=0;
m_pCVShadowMaps=0; //GET_CVAR("e_shadow_maps");
m_iPrevShadowMaps=0;
m_pCVVolFog=0; //GET_CVAR("r_volumetricfog");
m_iPrevVolFog=0;
m_pCVFog=0; //GET_CVAR("e_fog");
m_iPrevFog=0;
};
~CScreenVars()
{
Release();
};
// shaders used:
// color transfer shaders
void *m_pRCColorTransfer;
void *m_pVPColorTransfer;
// motion blur shaders
void *m_pRCMotion,
*m_pRCMotionAmount;
void *m_pVPMotion;
// blury screen shaders
void *m_pRCBluryScreen;
void *m_pVPBluryScreen;
// image enhancement shaders
void *m_pRCGlareMap,
*m_pRCGlareAmountMap,
*m_pRCGlare,
*m_pRCRenderModeCold,
*m_pRCRenderModeAdv;
void *m_pVPGlare;
// nightvision shaders
void *m_pRCNightVision;
void *m_pVPNightVision;
// heatvision shaders
void *m_pRCHeatVision,
*m_pRCHeatSourceDecode;
// flashbang shaders
void *m_pRCFlashBang;
void *m_pVPFlashBang;
// cartoon shaders
void *m_pRCCartoon,
*m_pRCCartoonSilhouette;
void *m_pVPCartoon;
// depth of field shaders
void *m_pRCDof;
// shared shaders
void *m_pRCBlur;
void *m_pRCBlurRECT;
void *m_pVPBlur;
void *m_pRCReplRgbToAlpha;
// fade process vars
bool m_bFadeActive;
float m_fFadeTime,
m_fFadeCurrTime,
m_fFadePreTime,
m_fFadeCurrPreTime;
color4f m_pFadeColor,
m_pFadeCurrColor;
// color transfer vars
bool m_bColorTransferActive;
color4f m_pColorTransferColor;
float m_fColorTransferAmount;
// motion blur vars
bool m_bMotionBlurActive;
float m_fMotionBlurAmount;
int m_iMotionBlurType,
m_iMotionBlurDisplace;
// blury screen vars
bool m_bBlurActive;
float m_fBlurAmount;
float m_iBlurWidth,
m_iBlurHeight;
color4f m_pBlurColor;
// image enhancement vars
bool m_bGlareActive;
int m_iGlareBox,
m_iGlareLumSize,
m_iGlareSize;
float m_fGlareAmount,
m_fGlareThreshold,
m_fGlareAmountDynamic,
m_fGlareMaxAmount;
color4f m_pCurrGlareMapConst,
m_pCurrSaturation,
m_pCurrContrast;
// nightvision vars
int m_iNightVisionActive;
color4f m_pNightVisionColor;
// heatvision vars
int m_iHeatVisionActive;
ICVar *m_pCVHeatVision; //GET_CVAR("CV_r_cryvision");
// flashbang vars
bool m_bFlashBangActive;
int m_iFlashBangForce;
float m_fFlashBangTimeScale,
m_fFlashBangTimeOut,
m_fFlashBangFlashPosX,
m_fFlashBangFlashPosY,
m_fFlashBangFlashSizeX,
m_fFlashBangFlashSizeY;
// cartoon rendering vars
bool m_bCartoonActive;
// depth of field vars
bool m_bDofActive;
float m_fDofFocalDistance;
// screen texture vars
bool m_bScreenTexActive;
// console vars
ICVar *m_pCVDisableSfx; //GET_CVAR("r_DisableSfx");
ICVar *m_pCVResetSfx; //GET_CVAR("r_ResetScreenFx");
ICVar *m_pCVNormalGlare; //GET_CVAR("r_Glare");
ICVar *m_pCVMotionBlur; //GET_CVAR("r_MotionBlur");
ICVar *m_pCVScreenColorTransfer; //GET_CVAR("r_ScreenColorTransfer");
ICVar *m_pCVMotionBlurAmount; //GET_CVAR("r_MotionBlurAmount");
ICVar *m_pCVMotionBlurDisplace; //GET_CVAR("r_MotionBlurDisplace");
ICVar *m_pCVRenderMode; //GET_CVAR("r_RenderMode");
// note: these are used for correct cryvision functioning
ICVar *m_pCVStencilShadows; //GET_CVAR("e_stencil_shadows")
int m_iPrevStencilShadows;
ICVar *m_pCVShadowMaps; //GET_CVAR("e_shadow_maps");
int m_iPrevShadowMaps;
ICVar *m_pCVVolFog; //GET_CVAR("r_volumetricfog");
int m_iPrevVolFog;
ICVar *m_pCVFog; //GET_CVAR("e_fog");
int m_iPrevFog;
ICVar *m_pCVMaxTexLodBias; //GET_CVAR("r_MaxTexLodBias");
float m_fPrevMaxTexLodBias;
void Create(void);
void Release(void);
void Reset(void);
};
#endif

View File

@@ -0,0 +1,670 @@
/*
=======================================================================
FILE : CREScreenProcess.cpp
DESC : screen processing render element
PROJ : Crytek Engine
CODER: Tiago Sousa
TODO:
.Convert all screen based effects into this interface
Last Update: 16/06/2003
=======================================================================
*/
#include "RenderPCH.h"
// some helper macros
#define SET_PARAMETER(pProcess, pParam, pType, pValue) \
case (pProcess): (pParam)=*((pType*) pValue); break; \
#define RETURN_PARAMETER(pProcess, pParam) \
case (pProcess): return (void*)&pParam;\
// constructor/destructor
CREScreenProcess::CREScreenProcess()
{
// setup screen process renderer type
mfSetType(eDATA_ScreenProcess);
mfUpdateFlags(FCEF_TRANSFORM);
m_pVars=0;
// create class vars if necessary...
if(!m_pVars)
{
m_pVars=new CScreenVars;
m_pVars->Create();
}
}
CREScreenProcess::~CREScreenProcess()
{
SAFE_DELETE(m_pVars)
};
// prepare screen processing
void CREScreenProcess:: mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
// make sure this is not processed, when rendering to refractive texture..
if (gRenDev->m_RP.m_bDrawToTexture)
{
gRenDev->m_RP.m_pRE = NULL;
}
else
{
gRenDev->m_RP.m_pRE = this;
}
gRenDev->m_RP.m_FlagsPerFlush |= RBSI_DRAWAS2D;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
void CREScreenProcess::mfReset()
{
if(m_pVars)
{
m_pVars->Reset();
}
}
// activate screen processes
void CREScreenProcess:: mfActivate(int pProcess)
{
switch(pProcess)
{
case SCREENPROCESS_FADE:
if(m_pVars->m_fFadeTime)
{
m_pVars->m_bFadeActive=1;
}
else
{
// reset fade
m_pVars->m_bFadeActive=0;
m_pVars->m_fFadePreTime=0.0f;
m_pVars->m_fFadeCurrPreTime=0.0f;
}
break;
case SCREENPROCESS_BLUR:
m_pVars->m_bBlurActive=1;
break;
case SCREENPROCESS_COLORTRANSFER:
m_pVars->m_bColorTransferActive=1;
break;
case SCREENPROCESS_MOTIONBLUR:
m_pVars->m_bMotionBlurActive=1;
break;
case SCREENPROCESS_GLARE:
m_pVars->m_bGlareActive=1;
break;
case SCREENPROCESS_NIGHTVISION:
// m_pVars->m_bNightVisionActive=1;
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_pCVHeatVision->Set(1);
}
break;
case SCREENPROCESS_HEATVISION:
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_pCVHeatVision->Set(1);
}
break;
case SCREENPROCESS_CARTOON:
m_pVars->m_bCartoonActive=1;
// reset fade amount
if(iConsole)
{
if(m_pVars->m_pCVMaxTexLodBias)
{
if(m_pVars->m_bCartoonActive)
{
m_pVars->m_fPrevMaxTexLodBias=m_pVars->m_pCVMaxTexLodBias->GetFVal();
m_pVars->m_pCVMaxTexLodBias->Set(-1.5f);
}
else
{
m_pVars->m_fPrevMaxTexLodBias=m_pVars->m_pCVMaxTexLodBias->GetFVal();
m_pVars->m_pCVMaxTexLodBias->Set(0.0f);
}
}
}
break;
case SCREENPROCESS_FLASHBANG:
m_pVars->m_bFlashBangActive=1;
// reset flash time out
m_pVars->m_fFlashBangTimeOut=1.0f;
break;
case SCREENPROCESS_DOF:
m_pVars->m_bDofActive=1;
// reset dof focal distance plane
m_pVars->m_fDofFocalDistance=20.0f;
break;
default:
break;
};
}
// set screen processing parameters
int CREScreenProcess:: mfSetParameter(int iProcess, int iParams, void *dwValue)
{
switch(iProcess)
{
// set screen fade parameters
case SCREENPROCESS_FADE:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_FADECOLOR, m_pVars->m_pFadeColor, color4f, dwValue)
case SCREENPROCESS_ACTIVE:
if(*((bool*) dwValue)==1)
{
m_pVars->m_bFadeActive=1;
}
else
{
// reset fade
m_pVars->m_bFadeActive=0;
m_pVars->m_fFadePreTime=0.0f;
m_pVars->m_fFadeCurrPreTime=0.0f;
}
break;
case SCREENPROCESS_TRANSITIONTIME:
m_pVars->m_fFadeTime=*((float*) dwValue);
m_pVars->m_fFadeCurrTime=(float) fabs(*((float*) dwValue));
break;
SET_PARAMETER(SCREENPROCESS_PRETRANSITIONTIME, m_pVars->m_fFadePreTime, float, dwValue)
}
break;
// set screen blur parameters
case SCREENPROCESS_BLUR:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_BLURAMOUNT, m_pVars->m_fBlurAmount, float, dwValue)
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bBlurActive, bool, dwValue)
case SCREENPROCESS_BLURCOLORRED:
m_pVars->m_pBlurColor.r=*(float*)dwValue;
break;
case SCREENPROCESS_BLURCOLORGREEN:
m_pVars->m_pBlurColor.g=*(float*)dwValue;
break;
case SCREENPROCESS_BLURCOLORBLUE:
m_pVars->m_pBlurColor.b=*(float*)dwValue;
break;
}
break;
// set color transfer parameters
case SCREENPROCESS_COLORTRANSFER:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_COLORTRANSFERAMOUNT, m_pVars->m_fColorTransferAmount, float, dwValue)
SET_PARAMETER(SCREENPROCESS_COLORTRANSFERCOLOR, m_pVars->m_pColorTransferColor, color4f, dwValue)
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bColorTransferActive, bool, dwValue)
}
break;
// set motion blur parameters
case SCREENPROCESS_MOTIONBLUR:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_MOTIONBLURDISPLACE, m_pVars->m_iMotionBlurDisplace, int, dwValue)
SET_PARAMETER(SCREENPROCESS_MOTIONBLURAMOUNT, m_pVars->m_fMotionBlurAmount, float, dwValue)
SET_PARAMETER(SCREENPROCESS_MOTIONBLURTYPE, m_pVars->m_iMotionBlurType, int, dwValue)
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bMotionBlurActive, bool, dwValue)
}
break;
// set glare parameters
case SCREENPROCESS_GLARE:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bGlareActive, bool, dwValue)
SET_PARAMETER(SCREENPROCESS_GLAREAMOUNT, m_pVars->m_fGlareAmount, float, dwValue)
SET_PARAMETER(SCREENPROCESS_GLARELUMSIZE, m_pVars->m_iGlareLumSize, int, dwValue)
SET_PARAMETER(SCREENPROCESS_GLAREMAXAMOUNT, m_pVars->m_fGlareMaxAmount, float, dwValue)
SET_PARAMETER(SCREENPROCESS_GLAREBOXSIZE, m_pVars->m_iGlareSize, int, dwValue)
SET_PARAMETER(SCREENPROCESS_GLARETHRESHOLD, m_pVars->m_fGlareThreshold, float, dwValue)
}
break;
// set nightvision parameters
case SCREENPROCESS_NIGHTVISION:
switch(iParams)
{
//SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bNightVisionActive, bool, dwValue)
case SCREENPROCESS_ACTIVE:
// m_pVars->m_bNightVisionActive=*(bool*)dwValue;
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_pCVHeatVision->Set(*((int*) dwValue));
/*
// must disable some rendering in order to cryvision function properly
if(m_pVars->m_pCVHeatVision->GetIVal())
{
m_pVars->m_iPrevStencilShadows=m_pVars->m_pCVStencilShadows->GetIVal();
m_pVars->m_iPrevShadowMaps=m_pVars->m_pCVShadowMaps->GetIVal();
m_pVars->m_iPrevVolFog=m_pVars->m_pCVVolFog->GetIVal();
//m_pVars->m_iPrevFog=m_pVars->m_pCVFog->GetIVal();
m_pVars->m_pCVStencilShadows->Set(0);
m_pVars->m_pCVShadowMaps->Set(0);
m_pVars->m_pCVVolFog->Set(0);
//m_pVars->m_pCVFog->Set(0);
}
else
{
m_pVars->m_pCVStencilShadows->Set(m_pVars->m_iPrevStencilShadows);
m_pVars->m_pCVShadowMaps->Set(m_pVars->m_iPrevShadowMaps);
m_pVars->m_pCVVolFog->Set(m_pVars->m_iPrevVolFog);
//m_pVars->m_pCVFog->Set(m_pVars->m_iPrevFog);
}*/
}
break;
case SCREENPROCESS_NIGHTVISIONCOLORRED:
m_pVars->m_pNightVisionColor.r=*(float*)dwValue;
break;
case SCREENPROCESS_NIGHTVISIONCOLORGREEN:
m_pVars->m_pNightVisionColor.g=*(float*)dwValue;
break;
case SCREENPROCESS_NIGHTVISIONCOLORBLUE:
m_pVars->m_pNightVisionColor.b=*(float*)dwValue;
break;
}
break;
// set heatvision parameters
case SCREENPROCESS_HEATVISION:
switch(iParams)
{
case SCREENPROCESS_ACTIVE:
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_pCVHeatVision->Set(*((int*) dwValue));
}
break;
//SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bHeatVisionActive, bool, dwValue)
}
break;
// set flashbang parameters
case SCREENPROCESS_FLASHBANG:
switch(iParams)
{
case SCREENPROCESS_ACTIVE:
m_pVars->m_bFlashBangActive= *((bool*) dwValue);
// reset flash time out
m_pVars->m_fFlashBangTimeOut=1.0f;
break;
SET_PARAMETER(SCREENPROCESS_FLASHBANGTIMESCALE, m_pVars->m_fFlashBangTimeScale, float, dwValue)
SET_PARAMETER(SCREENPROCESS_FLASHBANGFLASHPOSX, m_pVars->m_fFlashBangFlashPosX, float, dwValue)
SET_PARAMETER(SCREENPROCESS_FLASHBANGFLASHPOSY, m_pVars->m_fFlashBangFlashPosY, float, dwValue)
SET_PARAMETER(SCREENPROCESS_FLASHBANGFLASHSIZEX, m_pVars->m_fFlashBangFlashSizeX, float, dwValue)
SET_PARAMETER(SCREENPROCESS_FLASHBANGFLASHSIZEY, m_pVars->m_fFlashBangFlashSizeY, float, dwValue)
SET_PARAMETER(SCREENPROCESS_FLASHBANGFORCEAFTERIMAGE, m_pVars->m_iFlashBangForce, int, dwValue)
}
break;
// set cartoon parameters
case SCREENPROCESS_CARTOON:
switch(iParams)
{
//SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bCartoonActive, bool, dwValue)
case SCREENPROCESS_ACTIVE:
m_pVars->m_bCartoonActive= *((bool*) dwValue);
break;
}
break;
// set dof parameters
case SCREENPROCESS_DOF:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bDofActive, bool, dwValue)
SET_PARAMETER(SCREENPROCESS_DOFFOCALDISTANCE, m_pVars->m_fDofFocalDistance, float, dwValue)
}
break;
// set screentex parameters
case SCREENPROCESS_SCREENTEX:
switch(iParams)
{
SET_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bScreenTexActive, bool, dwValue)
}
break;
//default:
// break;
}
return 0;
}
// get screen processing parameters
void *CREScreenProcess:: mfGetParameter(int iProcess, int iParams)
{
switch(iProcess)
{
// return screen fade parameters
case SCREENPROCESS_FADE:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_TRANSITIONTIME, m_pVars->m_fFadeTime)
RETURN_PARAMETER(SCREENPROCESS_PRETRANSITIONTIME, m_pVars->m_fFadePreTime)
RETURN_PARAMETER(SCREENPROCESS_FADECOLOR, m_pVars->m_pFadeColor)
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bFadeActive)
}
break;
// return screen blur parameters
case SCREENPROCESS_BLUR:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_BLURAMOUNT, m_pVars->m_fBlurAmount)
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bBlurActive)
RETURN_PARAMETER(SCREENPROCESS_BLURCOLORRED, m_pVars->m_pBlurColor.r)
RETURN_PARAMETER(SCREENPROCESS_BLURCOLORGREEN, m_pVars->m_pBlurColor.g)
RETURN_PARAMETER(SCREENPROCESS_BLURCOLORBLUE, m_pVars->m_pBlurColor.b)
}
break;
// return color transfer parameters
case SCREENPROCESS_COLORTRANSFER:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_COLORTRANSFERAMOUNT, m_pVars->m_fColorTransferAmount)
RETURN_PARAMETER(SCREENPROCESS_COLORTRANSFERCOLOR, m_pVars->m_pColorTransferColor)
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bColorTransferActive)
}
break;
// return motion blur parameters
case SCREENPROCESS_MOTIONBLUR:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_MOTIONBLURDISPLACE, m_pVars->m_iMotionBlurDisplace)
RETURN_PARAMETER(SCREENPROCESS_MOTIONBLURAMOUNT, m_pVars->m_fMotionBlurAmount)
RETURN_PARAMETER(SCREENPROCESS_MOTIONBLURTYPE, m_pVars->m_iMotionBlurType)
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bMotionBlurActive)
}
break;
// return glare parameters
case SCREENPROCESS_GLARE:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bGlareActive)
RETURN_PARAMETER(SCREENPROCESS_GLAREAMOUNT, m_pVars->m_fGlareAmount)
RETURN_PARAMETER(SCREENPROCESS_GLARELUMSIZE, m_pVars->m_iGlareLumSize)
RETURN_PARAMETER(SCREENPROCESS_GLAREMAXAMOUNT, m_pVars->m_fGlareMaxAmount)
RETURN_PARAMETER(SCREENPROCESS_GLAREBOXSIZE, m_pVars->m_iGlareSize)
RETURN_PARAMETER(SCREENPROCESS_GLARETHRESHOLD, m_pVars->m_fGlareThreshold)
}
break;
// return nightvision parameters
case SCREENPROCESS_NIGHTVISION:
switch(iParams)
{
case SCREENPROCESS_ACTIVE:
//RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bNightVisionActive)
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_iNightVisionActive=m_pVars->m_pCVHeatVision->GetIVal();
}
return (void*)&m_pVars->m_iNightVisionActive;
break;
RETURN_PARAMETER(SCREENPROCESS_NIGHTVISIONCOLORRED, m_pVars->m_pNightVisionColor.r)
RETURN_PARAMETER(SCREENPROCESS_NIGHTVISIONCOLORGREEN, m_pVars->m_pNightVisionColor.g)
RETURN_PARAMETER(SCREENPROCESS_NIGHTVISIONCOLORBLUE, m_pVars->m_pNightVisionColor.b)
}
break;
// return heatvision parameters
case SCREENPROCESS_HEATVISION:
switch(iParams)
{
case SCREENPROCESS_ACTIVE:
if(m_pVars->m_pCVHeatVision)
{
m_pVars->m_iHeatVisionActive=m_pVars->m_pCVHeatVision->GetIVal();
}
return (void*)&m_pVars->m_iHeatVisionActive;
break;
//RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bHeatVisionActive)
}
break;
// return flashbang parameters
case SCREENPROCESS_FLASHBANG:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bFlashBangActive)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGTIMESCALE, m_pVars->m_fFlashBangTimeScale)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGTIMEOUT, m_pVars->m_fFlashBangTimeOut)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGFLASHPOSX, m_pVars->m_fFlashBangFlashPosX)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGFLASHPOSY, m_pVars->m_fFlashBangFlashPosY)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGFLASHSIZEX, m_pVars->m_fFlashBangFlashSizeX)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGFLASHSIZEY, m_pVars->m_fFlashBangFlashSizeY)
RETURN_PARAMETER(SCREENPROCESS_FLASHBANGFORCEAFTERIMAGE, m_pVars->m_iFlashBangForce)
}
break;
// return cartoon parameters
case SCREENPROCESS_CARTOON:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bCartoonActive)
}
break;
// return dof parameters
case SCREENPROCESS_DOF:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bDofActive)
RETURN_PARAMETER(SCREENPROCESS_DOFFOCALDISTANCE, m_pVars->m_fDofFocalDistance)
}
break;
// return screentex parameters
case SCREENPROCESS_SCREENTEX:
switch(iParams)
{
RETURN_PARAMETER(SCREENPROCESS_ACTIVE, m_pVars->m_bScreenTexActive)
}
break;
default:
break;
}
return 0;
}
// get shaders
void CScreenVars:: Create(void)
{
#if SHADERSCHECK
m_pRCBlur = CPShader::mfForName("CGRCBlur");
#ifdef OPENGL
m_pRCBlurRECT = CPShader::mfForName("CGRCBlurRECT");
#else
m_pRCBlurRECT = NULL;
#endif
m_pVPBlur = CVProgram::mfForName("CGVProgBlur");
m_pRCMotion = CPShader::mfForName("CGRCMotion");
m_pRCMotionAmount = CPShader::mfForName("CGRCMotionAmount");
m_pVPMotion = CVProgram::mfForName("CGVProgMotion");
m_pRCGlareMap = CPShader::mfForName("CGRCGlareMap");
m_pRCGlareAmountMap = CPShader::mfForName("CGRCGlareAmount");
m_pRCGlare = CPShader::mfForName("CGRCGlare");
m_pRCRenderModeCold = CPShader::mfForName("CGRCRenderModeCold");
m_pRCRenderModeAdv= CPShader::mfForName("CGRCRenderModeAdv");
m_pVPGlare = CVProgram::mfForName("CGVProgGlare");
m_pRCColorTransfer = CPShader::mfForName("CGRCColorTransfer");
m_pVPColorTransfer = CVProgram::mfForName("CGVProgColorTransfer");
m_pRCBluryScreen = CPShader::mfForName("CGRCBluryScreen");
m_pVPBluryScreen = CVProgram::mfForName("CGVProgBluryScreen");
m_pRCNightVision = CPShader::mfForName("CGRCNightVisionGlare");
m_pVPNightVision = CVProgram::mfForName("CGVProgNightVisionGlare");
m_pRCHeatVision = CPShader::mfForName("CGRCHeatSourcePass");
m_pRCHeatSourceDecode = CPShader::mfForName("CGRCHeatSourceDecode");
m_pVPFlashBang = CVProgram::mfForName("CGVProg_FlashBang");
m_pRCFlashBang = CPShader::mfForName("CGRCFlashBang");
m_pVPCartoon = CVProgram::mfForName("CGVProgCartoon");
m_pRCCartoon = CPShader::mfForName("CGRCCartoon");
m_pRCCartoonSilhouette = CPShader::mfForName("CGRCCartoonSilhouete");
m_pRCDof = CPShader::mfForName("CGRCDof");
m_pRCReplRgbToAlpha = CPShader::mfForName("CGRCReplRgbToAlpha");
#endif
if(iConsole)
{
m_pCVDisableSfx= iConsole->GetCVar("r_DisableSfx");
m_pCVResetSfx=iConsole->GetCVar("r_ResetScreenFx");
m_pCVNormalGlare=iConsole->GetCVar("r_Glare");
m_pCVMotionBlur=iConsole->GetCVar("r_MotionBlur");
m_pCVScreenColorTransfer=iConsole->GetCVar("r_ScreenColorTransfer");
m_pCVMotionBlurAmount=iConsole->GetCVar("r_MotionBlurAmount");
m_pCVMotionBlurDisplace=iConsole->GetCVar("r_MotionBlurDisplace");
m_pCVRenderMode=iConsole->GetCVar("r_RenderMode");
// note: these are used for correct cryvision functioning
m_pCVStencilShadows=iConsole->GetCVar("e_stencil_shadows");
m_iPrevStencilShadows=m_pCVStencilShadows->GetIVal();
m_pCVShadowMaps=iConsole->GetCVar("e_shadow_maps");
m_iPrevShadowMaps=m_pCVShadowMaps->GetIVal();
m_pCVVolFog=iConsole->GetCVar("r_VolumetricFog");
m_iPrevVolFog= m_pCVVolFog->GetIVal();
m_pCVFog=iConsole->GetCVar("e_fog");
m_iPrevFog=m_pCVFog->GetIVal();
m_pCVMaxTexLodBias=iConsole->GetCVar("r_MaxTexLodBias");
m_fPrevMaxTexLodBias=m_pCVMaxTexLodBias->GetFVal();
m_pCVHeatVision=iConsole->GetCVar("r_Cryvision");
m_iHeatVisionActive=m_pCVHeatVision->GetIVal();
// reset fade amount
ICVar *pHudFadeAmount=iConsole->GetCVar("hud_fadeamount");
if(pHudFadeAmount)
{
pHudFadeAmount->Set(1);
}
}
// fade process vars
m_bFadeActive=0;
m_fFadeTime=0;
m_fFadePreTime=0;
m_fFadeCurrPreTime=0;
m_fFadeCurrTime=0;
m_pFadeColor.set(0,0,0,0);
m_pFadeCurrColor.set(0,0,0,0);
}
// release/free data..
void CScreenVars:: Release(void)
{
/* // check if cryvision is active when exiting game, need to restore console vars..
if(m_pCVHeatVision)
{
if(m_pCVHeatVision->GetIVal())
{
if(m_pCVStencilShadows)
{
m_pCVStencilShadows->Set(m_iPrevStencilShadows);
}
if(m_pCVShadowMaps->GetIVal())
{
m_pCVShadowMaps->Set(m_iPrevShadowMaps);
}
if(m_pCVVolFog->GetIVal())
{
m_pCVVolFog->Set(m_iPrevVolFog);
}
}
}
*/
}
// reset effects state
void CScreenVars:: Reset(void)
{
// color transfer vars
m_bColorTransferActive=0;
m_pColorTransferColor.set(0,0,0,0);
m_fColorTransferAmount=1;
// blury screen vars
m_bBlurActive=0;
m_fBlurAmount=1.0f;
m_pBlurColor.set(1,1,1,1);
// nightvision vars
m_iNightVisionActive=0;
m_pNightVisionColor.set(-0.1f, 0.2f, 0.11f, 1.0f);
// heatvision vars
if(m_pCVHeatVision)
{
// m_pHeatVision->Set(0);
m_iHeatVisionActive=m_pCVHeatVision->GetIVal();
}
else
{
m_iHeatVisionActive=0;
}
// flashbang vars
m_bFlashBangActive=0;
m_fFlashBangTimeScale=1.0f;
m_fFlashBangTimeOut=1.0f;
m_fFlashBangFlashPosX=200;
m_fFlashBangFlashPosY=100;
m_fFlashBangFlashSizeX=400;
m_fFlashBangFlashSizeY=400;
// screentex vars
m_bScreenTexActive=0;
m_pCurrGlareMapConst.set(0.2f, 0.2f, 0.2f, 1.0f);
m_pCurrSaturation.set(0.0f, 0.0f, 0.0f, 0.2f);
m_pCurrContrast.set(0.0f, 0.0f, 0.85f, 0.15f);
// reset fade amount
ICVar *pHudFadeAmount=iConsole->GetCVar("hud_fadeamount");
if(pHudFadeAmount)
{
pHudFadeAmount->Set(1);
}
m_bFadeActive=0;
m_fFadeTime=0;
m_fFadePreTime=0;
m_fFadeCurrPreTime=0;
m_fFadeCurrTime=0;
m_pFadeColor.set(0,0,0,0);
m_pFadeCurrColor.set(0,0,0,0);
}

View File

@@ -0,0 +1,54 @@
/*
=====================================================================
FILE : CREScreenProcess.h
DESC : Screen processing render element
PROJ : Crytek Engine
CODER: Tiago Sousa
Last Update: 13/06/2003
=====================================================================
*/
#ifndef __CRESCREENPROCESS_H__
#define __CRESCREENPROCESS_H__
// screen processing vars class
class CScreenVars;
// screen processing render element
class CREScreenProcess : public CRendElement
{
friend class CD3D9Renderer;
friend class CGLRenderer;
public:
// constructor/destructor
CREScreenProcess();
virtual ~CREScreenProcess();
// prepare screen processing
virtual void mfPrepare();
// render screen processing
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
// begin screen processing
virtual void mfActivate(int iProcess);
// reset
virtual void mfReset(void);
// set/get methods
virtual int mfSetParameter(int iProcess, int iParams, void *dwValue);
virtual void *mfGetParameter(int iProcess, int iParams);
CScreenVars *GetVars() { return m_pVars; }
private:
virtual bool mfDrawLowSpec(SShader *ef, SShaderPass *sfm);
// screen processing vars class
CScreenVars *m_pVars;
};
#endif

View File

@@ -0,0 +1,22 @@
#include "RenderPCH.h"
#include "RendElement.h"
/*
void CREShadowMap::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_DynLMask |= m_DynMask;
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
CREShadowMap::~CREShadowMap()
{
if(m_CustomData)
{
delete m_CustomData;
m_CustomData=0;
}
}
*/

View File

@@ -0,0 +1,326 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "CRESky.h"
#include "i3dengine.h"
void CRESky::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
bool CRESky::mfDraw(SShader *ef, SShaderPass *sfm)
{
int bPrevClipPl = gRenDev->m_RP.m_ClipPlaneEnabled;
if (bPrevClipPl)
gRenDev->EF_SetClipPlane(false, NULL, false);
if(sfm >= &ef->m_Passes[1] && ef->m_Sky)
{ // draw sky sphere vertices at pass 1
bool bPrevFog = gRenDev->EnableFog(false);
DrawSkySphere(ef->m_Sky->m_fSkyLayerHeight);
gRenDev->EnableFog(bPrevFog);
if (bPrevClipPl)
gRenDev->EF_SetClipPlane(true, &gRenDev->m_RP.m_CurClipPlane.m_Normal.x, gRenDev->m_RP.m_bClipPlaneRefract);
return true;
}
// pass 0 - skybox
if (!ef->m_Sky || !ef->m_Sky->m_SkyBox[0])
{
if (bPrevClipPl)
gRenDev->EF_SetClipPlane(true, &gRenDev->m_RP.m_CurClipPlane.m_Normal.x, gRenDev->m_RP.m_bClipPlaneRefract);
return false;
}
bool bPrevFog = gRenDev->EnableFog(false);
gRenDev->SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture | (eCA_Constant<<3), eCA_Texture | (eCA_Constant<<3));
if (gRenDev->m_bHeatVision)
gRenDev->SetMaterialColor(0.3f,0.3f,0.3f,1.0f);
else
gRenDev->SetMaterialColor(1,1,1,m_fAlpha);
if(m_fAlpha<1.f)
gRenDev->EF_SetState(GS_NODEPTHTEST | GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
else
gRenDev->EF_SetState(GS_NODEPTHTEST);
gRenDev->SetCullMode(R_CULL_BACK);
#if !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
CPShader *fpSky = NULL;
if (gRenDev->m_RP.m_PersFlags & RBPF_HDR)
{
if (!(ef->m_Flags & EF_SKY_HDR))
fpSky = PShaderForName(gRenDev->m_RP.m_PS_HDR_SkyFake, "CGRC_HDR_SkyFake_PS20");
else
fpSky = PShaderForName(gRenDev->m_RP.m_PS_HDR_Sky, "CGRC_HDR_Sky_PS20");
if (fpSky)
fpSky->mfSet(true, 0);
}
#endif
const float fSkyBoxSize = SKY_BOX_SIZE;
{ // top
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
{Vec3(fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 1, 1.f-1},
{Vec3(-fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 0, 1.f-1},
{Vec3(fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 1, 1.f-0},
{Vec3(-fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 0, 1.f-0}
};
gRenDev->SetTexture(ef->m_Sky->m_SkyBox[2]->m_Bind);
gRenDev->SetTexClampMode(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),4);
}
Vec3d camera = gRenDev->GetCamera().GetPos();
camera.z = max(0,camera.z);
float fWaterCamDiff = max(0,camera.z-m_fTerrainWaterLevel);
float fMaxDist = iSystem->GetI3DEngine()->GetMaxViewDist()/1024.f;
float P = (fWaterCamDiff)/128 + max(0,(fWaterCamDiff)*0.03f/fMaxDist);
float D = (fWaterCamDiff)/10.0f*fSkyBoxSize/124.0f - P + 8;
P*=m_fSkyBoxStretching;
if(m_fTerrainWaterLevel>camera.z && SRendItem::m_RecurseLevel==1)
{
P = (fWaterCamDiff);
D = (fWaterCamDiff);
}
{ // s
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
Vec3(-fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 1.0, 1.f-1.0,
Vec3(fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 0.0, 1.f-1.0,
Vec3(-fSkyBoxSize,-fSkyBoxSize,-P), 1.0, 1.f-0.5,
Vec3(fSkyBoxSize,-fSkyBoxSize,-P), 0.0, 1.f-0.5,
Vec3(-fSkyBoxSize,-fSkyBoxSize,-D), 1.0, 1.f-0.5,
Vec3(fSkyBoxSize,-fSkyBoxSize,-D), 0.0, 1.f-0.5
};
gRenDev->SetTexture(ef->m_Sky->m_SkyBox[1]->m_Bind);
gRenDev->SetTexClampMode(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),6);
}
{ // e
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
Vec3(-fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 1.0, 1.f-0.0,
Vec3(-fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 0.0, 1.f-0.0,
Vec3(-fSkyBoxSize, fSkyBoxSize,-P), 1.0, 1.f-0.5,
Vec3(-fSkyBoxSize,-fSkyBoxSize,-P), 0.0, 1.f-0.5,
Vec3(-fSkyBoxSize, fSkyBoxSize,-D), 1.0, 1.f-0.5,
Vec3(-fSkyBoxSize,-fSkyBoxSize,-D), 0.0, 1.f-0.5
};
gRenDev->SetTexture(ef->m_Sky->m_SkyBox[1]->m_Bind);
gRenDev->SetTexClampMode(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),6);
}
{ // n
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
Vec3(fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 1.0, 1.f-1.0,
Vec3(-fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 0.0, 1.f-1.0,
Vec3(fSkyBoxSize, fSkyBoxSize,-P), 1.0, 1.f-0.5,
Vec3(-fSkyBoxSize, fSkyBoxSize,-P), 0.0, 1.f-0.5,
Vec3(fSkyBoxSize, fSkyBoxSize,-D), 1.0, 1.f-0.5,
Vec3(-fSkyBoxSize, fSkyBoxSize,-D), 0.0, 1.f-0.5
};
gRenDev->SetTexture(ef->m_Sky->m_SkyBox[0]->m_Bind);
gRenDev->SetTexClampMode(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),6);
}
{ // w
struct_VERTEX_FORMAT_P3F_TEX2F data[] =
{
Vec3(fSkyBoxSize,-fSkyBoxSize, fSkyBoxSize), 1.0, 1.f-0.0,
Vec3(fSkyBoxSize, fSkyBoxSize, fSkyBoxSize), 0.0, 1.f-0.0,
Vec3(fSkyBoxSize,-fSkyBoxSize,-P), 1.0, 1.f-0.5,
Vec3(fSkyBoxSize, fSkyBoxSize,-P), 0.0, 1.f-0.5,
Vec3(fSkyBoxSize,-fSkyBoxSize,-D), 1.0, 1.f-0.5,
Vec3(fSkyBoxSize, fSkyBoxSize,-D), 0.0, 1.f-0.5
};
gRenDev->SetTexture(ef->m_Sky->m_SkyBox[0]->m_Bind);
gRenDev->SetTexClampMode(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (data,VERTEX_FORMAT_P3F_TEX2F)),6);
}
#if !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
if (fpSky)
fpSky->mfSet(false, 0);
#endif
DrawFogLayer();
DrawBlackPortal();
gRenDev->EnableFog(bPrevFog);
if (bPrevClipPl)
gRenDev->EF_SetClipPlane(true, &gRenDev->m_RP.m_CurClipPlane.m_Normal.x, gRenDev->m_RP.m_bClipPlaneRefract);
return true;
}
bool CRESky::DrawFogLayer()
{
if(!m_parrFogLayer)
m_parrFogLayer = new list2<struct_VERTEX_FORMAT_P3F_COL4UB>;
if(!m_parrFogLayer2)
m_parrFogLayer2 = new list2<struct_VERTEX_FORMAT_P3F_COL4UB>;
m_parrFogLayer->Clear();
m_parrFogLayer2->Clear();
const float fFogLayerRadius = SKY_BOX_SIZE;
if(gRenDev->m_FS.m_FogEnd>=256)
return true;
Vec3d camera = gRenDev->GetCamera().GetPos();
camera.z = max(0,camera.z);
float fLayerZ = -(max(0,gRenDev->m_FS.m_FogEnd-64)/(256-64))*SKY_BOX_SIZE - camera.z/35;
bool bRGB = (gRenDev->GetFeatures() & RFT_RGBA) != 0;
for(int i=0; i<=360; i+=30)
{
float rad = (i) * (gf_PI/180);
struct_VERTEX_FORMAT_P3F_COL4UB tmp;
tmp.xyz.x = cry_sinf(-rad)*fFogLayerRadius;
tmp.xyz.y = cry_cosf(-rad)*fFogLayerRadius;
if(bRGB)
{
tmp.color.bcolor[0] = uchar(gRenDev->m_FS.m_FogColor.r*255);
tmp.color.bcolor[1] = uchar(gRenDev->m_FS.m_FogColor.g*255);
tmp.color.bcolor[2] = uchar(gRenDev->m_FS.m_FogColor.b*255);
}
else
{
tmp.color.bcolor[2] = uchar(gRenDev->m_FS.m_FogColor.r*255);
tmp.color.bcolor[1] = uchar(gRenDev->m_FS.m_FogColor.g*255);
tmp.color.bcolor[0] = uchar(gRenDev->m_FS.m_FogColor.b*255);
}
tmp.color.bcolor[3] = uchar(255.f);
tmp.xyz.z = fLayerZ-SKY_BOX_SIZE/2;
m_parrFogLayer2->Add(tmp);
tmp.xyz.z = fLayerZ+SKY_BOX_SIZE/2;
m_parrFogLayer2->Add(tmp);
m_parrFogLayer->Add(tmp);
tmp.xyz.z = fLayerZ+SKY_BOX_SIZE;
tmp.color.bcolor[3] = 0;
m_parrFogLayer->Add(tmp);
}
#if !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
CPShader *fpSky = NULL;
if (gRenDev->m_RP.m_PersFlags & RBPF_HDR)
{
fpSky = PShaderForName(gRenDev->m_RP.m_PS_HDR_BaseCol, "CGRC_HDR_BaseCol_PS20");
if (fpSky)
fpSky->mfSet(true);
}
#endif
gRenDev->EF_SetState(GS_NODEPTHTEST | GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
gRenDev->SelectTMU(0);
gRenDev->m_TexMan->m_Text_White->Set();
gRenDev->EnableTMU(true);
gRenDev->DrawTriStrip(&(CVertexBuffer (m_parrFogLayer->GetElements(),VERTEX_FORMAT_P3F_COL4UB)),m_parrFogLayer->Count());
gRenDev->DrawTriStrip(&(CVertexBuffer (m_parrFogLayer2->GetElements(),VERTEX_FORMAT_P3F_COL4UB)),m_parrFogLayer2->Count());
#if !defined(PS2) && !defined (GC) && !defined (NULL_RENDERER)
if (fpSky)
fpSky->mfSet(false);
#endif
return true;
}
CRESky::~CRESky()
{
delete m_parrFogLayer;
delete m_parrFogLayer2;
}
// render black occlusion volumes mostly to hide seams in indoors
bool CRESky::DrawBlackPortal()
{
if(!m_arrvPortalVerts[0][0].xyz.x)
return true;
gRenDev->ResetToDefault();
for(int i=0; i<MAX_SKY_OCCLAREAS_NUM; i++)
{
if(!m_arrvPortalVerts[i][0].xyz.x)
return true;
gRenDev->EF_SetState(GS_DEPTHWRITE);
gRenDev->SetCullMode(R_CULL_NONE);
gRenDev->SelectTMU(0);
gRenDev->EnableTMU(false);
gRenDev->DrawTriStrip(&(CVertexBuffer (m_arrvPortalVerts[i],VERTEX_FORMAT_P3F_COL4UB)),4);
}
return true;
}
void CRESky::DrawSkySphere(float fHeight)
{
float nWSize = 256/16;
float a_in = 1, a_out = 1;
struct_VERTEX_FORMAT_P3F_COL4UB vert;
vert.color.bcolor[0]=255;
vert.color.bcolor[1]=255;
vert.color.bcolor[2]=255;
list2<struct_VERTEX_FORMAT_P3F_COL4UB> lstVertData;
for(float r=0; r<3; r++)
{
a_in = a_out;
a_out = 1.f-r/2;
a_out*=a_out; a_out*=a_out; a_out*=a_out;
lstVertData.Clear();
for(int i=0; i<=360; i+=40)
{
float rad = (i) * (M_PI/180);
vert.xyz.x = cry_sinf(rad)*nWSize*r;
vert.xyz.y = cry_cosf(rad)*nWSize*r;
vert.xyz.z = fHeight + 8 - (r)*8;
vert.color.bcolor[3] = uchar(a_in*255.0f);
lstVertData.Add(vert);
vert.xyz.x = cry_sinf(rad)*nWSize*(r+1);
vert.xyz.y = cry_cosf(rad)*nWSize*(r+1);
vert.xyz.z = fHeight + 8 - (r+1)*8;
vert.color.bcolor[3] = uchar(a_out*255.0f);
lstVertData.Add(vert);
}
gRenDev->DrawTriStrip(&CVertexBuffer(&lstVertData[0],VERTEX_FORMAT_P3F_COL4UB),lstVertData.Count());
}
}

View File

@@ -0,0 +1,32 @@
#ifndef __CRESKYZONE_H__
#define __CRESKYZONE_H__
//=============================================================
class CRESkyZone : public CRendElement
{
public:
Vec3d mViewPos;
Vec3d mMins;
Vec3d mMaxs;
Vec3d mCenter;
float mRadius;
byte *mPVS;
CRESkyZone()
{
mfSetType(eDATA_SkyZone);
mfUpdateFlags(FCEF_TRANSFORM | FCEF_NODEL);
mPVS = NULL;
}
virtual ~CRESkyZone()
{
if (mPVS)
delete [] mPVS;
}
virtual bool mfCompile(SShader *ef, char *scr);
};
#endif // __CRESKYZONE_H__

View File

@@ -0,0 +1,36 @@
#include "RenderPCH.h"
#include "RendElement.h"
void CRETempMesh::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 6;
gRenDev->m_RP.m_RendNumVerts = 4;
gRenDev->m_RP.m_FirstVertex = 0;
gRenDev->m_RP.m_FirstIndex = 0;
}
void *CRETempMesh::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
*Stride = sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F);
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *pVertices = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)m_VBuffer->m_VS[VSF_GENERAL].m_VData;
gRenDev->m_RP.m_nCurBufferID = m_VBuffer->m_VS[VSF_GENERAL].m_VertBuf.m_nID;
SBufInfoTable *pOffs = &gBufInfoTable[m_VBuffer->m_vertexformat];
switch(ePT)
{
case eSrcPointer_Vert:
gRenDev->m_RP.m_nCurBufferOffset = 0;
return &pVertices->xyz.x;
case eSrcPointer_Tex:
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsTC;
return &pVertices->st[0];
case eSrcPointer_Color:
gRenDev->m_RP.m_nCurBufferOffset = pOffs->OffsColor;
return &pVertices->color.dcolor;
}
return NULL;
}

View File

@@ -0,0 +1,48 @@
#ifndef __CRETEMPMESH_H__
#define __CRETEMPMESH_H__
//=============================================================
class CRETempMesh : public CRendElement
{
public:
CVertexBuffer *m_VBuffer;
SVertexStream m_Inds;
public:
CRETempMesh()
{
m_VBuffer = NULL;
m_Inds.Reset();
mfSetType(eDATA_TempMesh);
mfUpdateFlags(FCEF_TRANSFORM);
}
virtual ~CRETempMesh()
{
if (m_VBuffer)
{
gRenDev->ReleaseBuffer(m_VBuffer);
m_VBuffer = NULL;
}
gRenDev->ReleaseIndexBuffer(&m_Inds);
m_Inds.Reset();
}
virtual void mfPrepare();
virtual bool mfDraw(SShader *ef, SShaderPass *sfm);
virtual void *mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags);
virtual bool mfPreDraw(SShaderPass *sl);
virtual void mfReset();
virtual int Size()
{
int nSize = sizeof(*this);
if (m_VBuffer)
nSize += m_VBuffer->Size(0, m_VBuffer->m_NumVerts);
return nSize;
}
};
#endif // __CRETEMPMESH_H__

View File

@@ -0,0 +1,32 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "CRETerrainSector.h"
#include "I3DEngine.h"
void CRECommon::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
bool CREFarTreeSprites::mfDraw(SShader *ef, SShaderPass *sfm)
{
iSystem->GetI3DEngine()->DrawFarTrees();
return true;
}
bool CRETerrainDetailTextureLayers::mfDraw(SShader *ef, SShaderPass *sfm)
{
iSystem->GetI3DEngine()->DrawTerrainDetailTextureLayers();
return true;
}
bool CRETerrainParticles::mfDraw(SShader *ef, SShaderPass *sfm)
{
iSystem->GetI3DEngine()->DrawTerrainParticles(ef);
return true;
}

View File

@@ -0,0 +1,17 @@
#include "RenderPCH.h"
/*
#include "RendElement.h"
#include "CRETriMeshAdditionalShadow.h"
//////////////////////////////////////////////////////////////////////
void CRETriMeshAdditionalShadow::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_DynLMask |= m_DynMask;
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
*/

View File

@@ -0,0 +1,247 @@
#include "RenderPCH.h"
#include "RendElement.h"
#include "CRETriMeshShadow.h"
#include "I3DEngine.h"
// shadow volumes rendering modified by vlad
// shadow volumes statistics
int CRETriMeshShadow::m_nCRETriMeshShadowRebuildsPerFrrame = 0;
int CRETriMeshShadow::m_nCRETriMeshShadowShadowsPerFrrame = 0;
int CRETriMeshShadow::m_nCRETriMeshShadowAloocatedShadows = 0;
//////////////////////////////////////////////////////////////////////
void CRETriMeshShadow::mfPrepare()
{
gRenDev->EF_CheckOverflow(0, 0, this);
gRenDev->m_RP.m_pRE = this;
gRenDev->m_RP.m_RendNumIndices = 0;
gRenDev->m_RP.m_RendNumVerts = 0;
}
//////////////////////////////////////////////////////////////////////
void *CRETriMeshShadow::mfGetPointer(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags)
{
switch (ePT)
{
case eSrcPointer_Vert:
{
if(m_nCurrInst<0)
{
// Warning( 0,0,"Error: CRETriMeshShadow::mfGetPointer: m_nCurrInst<0");
return NULL;
}
*Stride = m_VertexSize[m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer->m_vertexformat];
if(m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer)
return m_arrLBuffers[m_nCurrInst].pVB->m_pVertexBuffer->m_VS[VSF_GENERAL].m_VData;
else
Warning( 0,0,"Error: CRETriMeshShadow::mfGetPointer: m_pBuffer->m_pVertexBuffer == 0");
}
break;
}
return NULL;
}
int CRETriMeshShadow::GetAndResetRebuildsPerFrrameCounter()
{
int n = m_nCRETriMeshShadowRebuildsPerFrrame;
m_nCRETriMeshShadowRebuildsPerFrrame = 0;
return n;
}
int CRETriMeshShadow::GetAndResetShadowVolumesPerFrrameCounter()
{
int n = m_nCRETriMeshShadowShadowsPerFrrame;
m_nCRETriMeshShadowShadowsPerFrrame = 0;
return n;
}
int CRETriMeshShadow::GetShadowVolumesAllocatedCounter()
{
return m_nCRETriMeshShadowAloocatedShadows;
}
bool CRETriMeshShadow::mfCheckUpdate(int nVertFormat, int Flags)
{
if(m_bAnimatedObject)
{ // character animation: everything already calculated, always use slot 0
m_nCurrInst = 0; // will be used during drawing
ShadVolInstanceInfo * pSVInfo = &m_arrLBuffers[0];
if (pSVInfo->pVB->m_pMats && pSVInfo->pVB->m_pMats->Count() && pSVInfo->pVB->m_pMats->Get(0)->pRE)
return pSVInfo->pVB->m_pMats->Get(0)->pRE->mfCheckUpdate(nVertFormat, Flags);
return false;
}
m_nCRETriMeshShadowShadowsPerFrrame++;
assert(m_nCurrInst == -1);
// find light of this shadow
CDLight * pDLight = NULL;
if (gRenDev->m_RP.m_DynLMask)
{
for (int n=0; n<gRenDev->m_RP.m_DLights[SRendItem::m_RecurseLevel].Num(); n++)
{
if (gRenDev->m_RP.m_DynLMask & (1<<n))
{
pDLight = gRenDev->m_RP.m_DLights[SRendItem::m_RecurseLevel][n];
break;
}
}
}
if (!pDLight)
return true;
CDLight fakeLight;
fakeLight = *pDLight; // do not copy
// get obj space light pos
CCObject *pObj = gRenDev->m_RP.m_pCurObject;
Matrix44& tInvRot = pObj->GetInvMatrix();
fakeLight.m_vObjectSpacePos = tInvRot.TransformPointOLD(fakeLight.m_Origin);
// assert(m_nCurrInst==-1);
// todo: take radius into account
//assert(pObj->m_CustomData);
// find buffer for this case
ShadVolInstanceInfo * pSVInfo = 0;
for(int i=0; i<MAX_SV_INSTANCES; i++) // find static volume by light objspace position
if(m_arrLBuffers[i].pVB && IsEquivalent(m_arrLBuffers[i].vObjSpaceLightPos, fakeLight.m_vObjectSpacePos, 0.001f))
{
pSVInfo = &m_arrLBuffers[i];
pSVInfo->nFrameId = gRenDev->GetFrameID();
m_nCurrInst = i;
break;
}
if(!pSVInfo) // if not found - select new slot
{
// now find same combination of light and shadow caster
// but only if slot was not used in prev frame -
// outomagic double buffering of dynamic shadows
for(int i=0; i<MAX_SV_INSTANCES; i++)
if( m_arrLBuffers[i].pVB &&
m_arrLBuffers[i].pLightOwner == fakeLight.m_pOwner &&
m_arrLBuffers[i].pShadowCaster == pObj->m_CustomData &&
m_arrLBuffers[i].nFrameId+1 < gRenDev->GetFrameID())
{
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
break;
}
if(!pSVInfo) // if still not found
{ // find empty slot or slot with smallest frame id
int nSmalestFrameId = gRenDev->GetFrameID()+1;
for(int i=0; i<MAX_SV_INSTANCES; i++)
{
if(!m_arrLBuffers[i].pVB)
{ // search for free slot
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
nSmalestFrameId=0;
break;
}
if(m_arrLBuffers[i].nFrameId<nSmalestFrameId)
{ // search for oldest slot at the same time
nSmalestFrameId = m_arrLBuffers[i].nFrameId;
pSVInfo = &m_arrLBuffers[i];
m_nCurrInst = i;
}
}
}
if(pSVInfo)
{
pSVInfo->nFrameId = gRenDev->GetFrameID();
pSVInfo->vObjSpaceLightPos = fakeLight.m_vObjectSpacePos;
pSVInfo->pLightOwner = fakeLight.m_pOwner;
pSVInfo->pShadowCaster = (IEntityRender*)pObj->m_CustomData;
}
if(!pSVInfo->pVB)
m_nCRETriMeshShadowAloocatedShadows++; // will be created now
// pSVInfo will be used in RebuildDynamicShadowVolumeBuffer
m_pSvObj->RebuildShadowVolumeBuffer(fakeLight, pObj->m_TempVars[0]);
m_nCRETriMeshShadowRebuildsPerFrrame++;
// if(!pSVInfo->pVB)
// iLog->Log("Warning: CRETriMeshShadow::mfCheckUpdate: !pSVInfo->pVB");
/*
ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3 && pSVInfo->pVB)
iLog->Log("CRETriMeshShadow: Static shadow volume created: %d faces", pSVInfo->pVB->GetIndices().Count()/3);*/
}
if (pSVInfo->pVB &&
pSVInfo->pVB->m_pMats &&
pSVInfo->pVB->m_pMats->Count() &&
pSVInfo->pVB->m_pMats->Get(0)->pRE)
pSVInfo->pVB->m_pMats->Get(0)->pRE->mfCheckUpdate(nVertFormat, Flags);
else
m_nCurrInst = -1;
fakeLight.m_vObjectSpacePos = Vec3d(0,0,0);
#ifdef DIRECT3D8
assert(0); // not tested, what this line do?
gRenDev->m_RP.m_CurD3DVFormat = pSVInfo->pVB->m_pSecVertBuffer->m_vertexformat + 16;
#endif
return true;
}
CRETriMeshShadow::~CRETriMeshShadow()
{
for(int i=0; i<MAX_SV_INSTANCES; i++)
{
gRenDev->DeleteLeafBuffer(m_arrLBuffers[i].pVB);
m_arrLBuffers[i].pVB=0;
}
}
bool CRETriMeshShadow::mfCheckUnload()
{ // remove all not used leafbuffers
for(int i=0; i<MAX_SV_INSTANCES; i++)
if(m_arrLBuffers[i].pVB)
{
if(m_arrLBuffers[i].nFrameId < gRenDev->GetFrameID()-100)
{
gRenDev->DeleteLeafBuffer(m_arrLBuffers[i].pVB);
m_arrLBuffers[i].pVB=0;
m_arrLBuffers[i].nFrameId=0;
m_nCRETriMeshShadowAloocatedShadows--;
}
}
/*
if(nLastCRETriMeshShadowLogFrame != gRenDev->GetFrameID())
{
int nRebNum = GetRETriMeshShadowRebuildsPerFrrame()/32;;
int nShadNum = GetRETriMeshShadowShadowsPerFrrame()/32;
ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3)
iLog->Log("CRETriMeshShadow: Allocated: %d, Used: %d, Updated: %d",
nCRETriMeshShadowAloocatedShadows, nShadNum, nRebNum);
nLastCRETriMeshShadowLogFrame = gRenDev->GetFrameID();
}*/
return true;
}
void CRETriMeshShadow::PrintStats()
{
gRenDev->TextToScreenColor(8,20, 0,2,0,1, "Shadow volumes stats: Rebuild: %d, Used: %d, Allocated: %d",
CRETriMeshShadow::GetAndResetRebuildsPerFrrameCounter(),
CRETriMeshShadow::GetAndResetShadowVolumesPerFrrameCounter(),
CRETriMeshShadow::GetShadowVolumesAllocatedCounter());
}

View File

@@ -0,0 +1,526 @@
#include "RenderPCH.h"
// Not for AMD64
#if !defined(WIN64) && !defined(LINUX)
#pragma warning(push)
#pragma warning(disable:4731) // frame pointer register 'ebp' modified by inline assembly code
struct SConstSSE
{
float m_fVal0;
float m_fVal1;
float m_fVal2;
float m_fVal3;
};
_declspec(align(16)) SConstSSE _tabCoef64_1[4][6] =
{
{
{1.000000f, 0.995185f, 0.980785f, 0.956940f},
{0.000000f, -0.098017f, -0.195090f, -0.290285f},
{1.000000f, 0.980785f, 0.923880f, 0.831470f},
{0.000000f, -0.195090f, -0.382683f, -0.555570f},
{1.000000f, 0.956940f, 0.831470f, 0.634393f},
{0.000000f, -0.290285f, -0.555570f, -0.773010f},
},
{
{0.923880f, 0.881921f, 0.831470f, 0.773010f},
{-0.382683f, -0.471397f, -0.555570f, -0.634393f},
{0.707107f, 0.555570f, 0.382683f, 0.195090f},
{-0.707107f, -0.831470f, -0.923880f, -0.980785f},
{0.382683f, 0.098017f, -0.195090f, -0.471397f},
{-0.923880f, -0.995185f, -0.980785f, -0.881921f},
},
{
{0.707107f, 0.634393f, 0.555570f, 0.471397f},
{-0.707107f, -0.773010f, -0.831470f, -0.881921f},
{0.000000f, -0.195090f, -0.382683f, -0.555570f},
{-1.000000f, -0.980785f, -0.923880f, -0.831470f},
{-0.707107f, -0.881921f, -0.980785f, -0.995185f},
{-0.707107f, -0.471397f, -0.195090f, 0.098017f},
},
{
{0.382683f, 0.290285f, 0.195090f, 0.098017f},
{-0.923880f, -0.956940f, -0.980785f, -0.995185f},
{-0.707107f, -0.831470f, -0.923880f, -0.980785f},
{-0.707107f, -0.555570f, -0.382683f, -0.195090f},
{-0.923880f, -0.773010f, -0.555570f, -0.290285f},
{0.382683f, 0.634393f, 0.831470f, 0.956940f},
}
};
_declspec(align(16)) SConstSSE _tabCoef64_2[4][6] =
{
{
{1.000000f, 0.923880f, 0.707107f, 0.382683f},
{0.000000f, -0.382683f, -0.707107f, -0.923880f},
{1.000000f, 0.707107f, 0.000000f, -0.707107f},
{0.000000f, -0.707107f, -1.000000f, -0.707107f},
{1.000000f, 0.382683f, -0.707107f, -0.923880f},
{0.000000f, -0.923880f, -0.707107f, 0.382683f},
}
};
void cradix4c_64(float* ar, float* ai, int nm)
{
int wdt = OCEANGRID;
float *arw = &ar[wdt];
float *aiw = &ai[wdt];
_asm
{
mov eax, arw
mov ebx, aiw
mov edx, ai
mov ecx, ar
sub esp, 20h
mov [esp+0ch], ebp
mov [esp], ecx
mov [esp+4], edx
mov ebp, ecx
mov [esp+10h], eax
mov [esp+14h], ebx
mov [esp+18h], ebp
mov [esp+1ch], edx
lea ebx, [ebp+40h]
lea edi, _tabCoef64_1
mov [esp+8], ebx
_lAlign:
movaps xmm0,xmmword ptr [ebp]
movaps xmm4,xmm0
movaps xmm2,xmmword ptr [ebp+80h]
subps xmm0,xmm2
movaps xmm1,xmmword ptr [ebp+40h]
addps xmm4,xmm2
movaps xmm3,xmmword ptr [ebp+0C0h]
movaps xmm5,xmm1
movaps xmm2,xmmword ptr [edx]
addps xmm5,xmm3
jmp _lCicleAlign
align 4
_lStartAlign:
movaps xmmword ptr [edx+0B0h],xmm0
movaps xmm0,xmmword ptr [ebp]
subps xmm7,xmm4
movaps xmm4,xmm0
movaps xmmword ptr [ebp+0B0h],xmm5
addps xmm3,xmm1
movaps xmm2,xmmword ptr [ebp+80h]
movaps xmmword ptr [ebp+30h],xmm7
subps xmm0,xmm2
movaps xmm1,xmmword ptr [ebp+40h]
addps xmm4,xmm2
movaps xmm5,xmm1
movaps xmmword ptr [edx+30h],xmm3
movaps xmm2,xmmword ptr [edx]
movaps xmm3,xmmword ptr [ebp+0C0h]
addps xmm5,xmm3
_lCicleAlign:
align 4
movaps xmm7,xmm4
subps xmm1,xmm3
prefetcht0 [edi]
addps xmm4,xmm5
movaps xmm3,xmm2
movaps xmm6,xmmword ptr [edx+80h]
subps xmm7,xmm5
prefetcht0 [edi+10h]
movaps xmmword ptr [ebp],xmm4
addps xmm3,xmm6
movaps xmm5,xmmword ptr [edx+40h]
subps xmm2,xmm6
prefetcht0 [edi+20h]
movaps xmm4,xmmword ptr [edx+0C0h]
movaps xmm6,xmm5
addps xmm5,xmm4
prefetcht0 [edi+30h]
subps xmm6,xmm4
movaps xmm4,xmm5
addps xmm5,xmm3
movaps xmmword ptr [edx],xmm5
movaps xmm5,xmm0
addps xmm0,xmm6
prefetcht0 [edi+40h]
subps xmm3,xmm4
movaps xmm4,xmm2
subps xmm2,xmm1
prefetcht0 [edi+50h]
addps xmm1,xmm4
subps xmm5,xmm6
movaps xmm4,xmm0
movaps xmm6,xmm2
mulps xmm0,xmmword ptr [edi]
mulps xmm2,xmmword ptr [edi+10h]
mulps xmm4,xmmword ptr [edi+10h]
add ebp,10h
add edx,10h
subps xmm0,xmm2
mulps xmm6,xmmword ptr [edi]
movaps xmm2,xmm1
movaps xmmword ptr [ebp+70h],xmm0
mulps xmm1,xmmword ptr [edi+50h]
movaps xmm0,xmm5
addps xmm4,xmm6
mulps xmm5,xmmword ptr [edi+40h]
mulps xmm2,xmmword ptr [edi+40h]
mulps xmm0,xmmword ptr [edi+50h]
subps xmm5,xmm1
movaps xmmword ptr [edx+70h],xmm4
movaps xmm1,xmm7
mulps xmm7,xmmword ptr [edi+20h]
movaps xmm4,xmm3
addps xmm0,xmm2
mulps xmm3,xmmword ptr [edi+20h]
mulps xmm4,xmmword ptr [edi+30h]
cmp ebp,ebx
mulps xmm1,xmmword ptr [edi+30h]
lea edi,[edi+60h]
jl _lStartAlign
movaps xmmword ptr [ebp+0B0h],xmm5
addps xmm3,xmm1
subps xmm7,xmm4
movaps xmmword ptr [edx+0B0h],xmm0
movaps xmmword ptr [edx+30h],xmm3
movaps xmmword ptr [ebp+30h],xmm7
mov ebp,[esp]
mov edx,[esp+4]
add ebp,100h
add edx,100h
mov [esp],ebp
mov [esp+4],edx
cmp ebp,[esp+10h]
lea ebx,[ebp+40h]
mov [esp+8],ebx
lea edi,_tabCoef64_1
jl _lAlign
mov ebp, [esp+18h];
mov edx, [esp+1ch];
mov [esp], ebp
mov [esp+4], edx
lea ebx, [ebp+10h]
lea edi, _tabCoef64_2
mov [esp+8], ebx
_lAlign2:
movaps xmm0,xmmword ptr [ebp]
movaps xmm4,xmm0
movaps xmm2,xmmword ptr [ebp+20h]
subps xmm0,xmm2
movaps xmm1,xmmword ptr [ebp+10h]
addps xmm4,xmm2
movaps xmm3,xmmword ptr [ebp+30h]
movaps xmm5,xmm1
movaps xmm2,xmmword ptr [edx]
addps xmm5,xmm3
jmp _lCicleAlign2
align 4
_lStartAlign2:
movaps xmmword ptr [edx+20h],xmm0
movaps xmm0,xmmword ptr [ebp]
subps xmm7,xmm4
movaps xmm4,xmm0
movaps xmmword ptr [ebp+20h],xmm5
addps xmm3,xmm1
movaps xmm2,xmmword ptr [ebp+20h]
movaps xmmword ptr [ebp],xmm7
subps xmm0,xmm2
movaps xmm1,xmmword ptr [ebp+10h]
addps xmm4,xmm2
movaps xmm5,xmm1
movaps xmmword ptr [edx],xmm3
movaps xmm2,xmmword ptr [edx]
movaps xmm3,xmmword ptr [ebp+30h]
addps xmm5,xmm3
_lCicleAlign2:
movaps xmm7,xmm4
subps xmm1,xmm3
prefetcht0 [edi]
addps xmm4,xmm5
movaps xmm3,xmm2
movaps xmm6,xmmword ptr [edx+20h]
subps xmm7,xmm5
prefetcht0 [edi+10h]
movaps xmmword ptr [ebp],xmm4
addps xmm3,xmm6
movaps xmm5,xmmword ptr [edx+10h]
subps xmm2,xmm6
prefetcht0 [edi+20h]
movaps xmm4,xmmword ptr [edx+30h]
movaps xmm6,xmm5
addps xmm5,xmm4
prefetcht0 [edi+30h]
subps xmm6,xmm4
movaps xmm4,xmm5
addps xmm5,xmm3
movaps xmmword ptr [edx],xmm5
movaps xmm5,xmm0
addps xmm0,xmm6
prefetcht0 [edi+40h]
subps xmm3,xmm4
movaps xmm4,xmm2
subps xmm2,xmm1
prefetcht0 [edi+50h]
addps xmm1,xmm4
subps xmm5,xmm6
movaps xmm4,xmm0
movaps xmm6,xmm2
mulps xmm0,xmmword ptr [edi]
mulps xmm2,xmmword ptr [edi+10h]
mulps xmm4,xmmword ptr [edi+10h]
add ebp,10h
add edx,10h
subps xmm0,xmm2
mulps xmm6,xmmword ptr [edi]
movaps xmm2,xmm1
movaps xmmword ptr [ebp+10h],xmm0
mulps xmm1,xmmword ptr [edi+50h]
movaps xmm0,xmm5
addps xmm4,xmm6
mulps xmm5,xmmword ptr [edi+40h]
mulps xmm2,xmmword ptr [edi+40h]
mulps xmm0,xmmword ptr [edi+50h]
subps xmm5,xmm1
movaps xmmword ptr [edx+10h],xmm4
movaps xmm1,xmm7
mulps xmm7,xmmword ptr [edi+20h]
movaps xmm4,xmm3
addps xmm0,xmm2
mulps xmm3,xmmword ptr [edi+20h]
mulps xmm4,xmmword ptr [edi+30h]
cmp ebp,ebx
mulps xmm1,xmmword ptr [edi+30h]
lea edi,[edi+60h]
jl _lStartAlign2
movaps xmmword ptr [ebp+20h],xmm5
addps xmm3,xmm1
subps xmm7,xmm4
movaps xmmword ptr [edx+20h],xmm0
movaps xmmword ptr [edx],xmm3
movaps xmmword ptr [ebp],xmm7
mov ebp,[esp]
mov edx,[esp+4]
add ebp,40h
add edx,40h
mov [esp],ebp
mov [esp+4],edx
cmp ebp,[esp+10h]
lea ebx,[ebp+10h]
mov [esp+8],ebx
lea edi,_tabCoef64_2
jl _lAlign2
mov ebp, [esp+18h]
mov edx, [esp+1ch]
mov [esp], ebp
mov [esp+4], edx
mov ebx, [esp+10h]
fld dword ptr [ebp]
fld st(0)
fld dword ptr [ebp+8]
fsub st(1),st
faddp st(2),st
fld dword ptr [ebp+4]
fxch st(2)
fld st(2)
fld dword ptr [ebp+0Ch]
fadd st(1),st
fsubp st(4),st
jmp _lEnd3
align 4
_lCicle:
fstp dword ptr [ebp-4]
fld dword ptr [ebp]
fxch st(1)
fstp dword ptr [ebp-8]
fld st(0)
fld dword ptr [ebp+8]
fadd st(2),st
fxch st(3)
fstp dword ptr [edx-10h]
fsubrp st(2),st
fld dword ptr [ebp+4]
fld st(0)
fld dword ptr [ebp+0Ch]
fadd st(2),st
fxch st(5)
fstp dword ptr [edx-4]
fsubrp st(4),st
_lEnd3:
fld dword ptr [edx]
fld dword ptr [edx]
fld st(3)
fadd st,st(3)
fld dword ptr [edx+8]
fadd st(3),st
fxch st(5)
fsubrp st(4),st
fld dword ptr [edx+4]
fxch st(2)
fsubrp st(5),st
fstp dword ptr [ebp]
fld st(0)
fld dword ptr [edx+0Ch]
fadd st(2),st
fxch st(4)
fstp dword ptr [ebp+4]
fsubrp st(3),st
fst [esp+10h]
fadd st,st(1)
fxch st(4)
fst [esp+14h]
fadd st,st(2)
fxch st(3)
fst [esp+18h]
fsub st,st(5)
fld [esp+10h]
fsubp st(2),st
fld [esp+14h]
fsubrp st(3),st
fld [esp+18h]
faddp st(6),st
add ebp,10h
add edx,10h
fstp dword ptr [edx-8]
cmp ebp,ebx
fstp dword ptr [edx-0Ch]
jl _lCicle
fstp dword ptr [ebp-4]
fstp dword ptr [ebp-8]
fstp dword ptr [edx-10h]
fstp dword ptr [edx-4]
mov ebp, [esp+0ch]
add esp, 20h
}
}
void bittabc(int *p, int sn)
{
int i2 = sn;
int j = 1;
int i, k;
int ind = 0;
i2 >>= 1;
for (i=1; i<=sn-1; i++)
{
if (i < j)
{
ind += 2;
p[ind] = i-1;
p[ind+1] = j-1;
}
k = i2;
while (j > k)
{
j -= k;
k >>= 1;
}
j += k;
}
p[0] = 0;
p[1] = ind >> 1;
}
void coef4r22c(int *ptr, int nm)
{
int sn = 1<<nm;
bittabc(ptr, sn);
}
void cbitrevc(float* ar, float* ai, int *p)
{
int nCount = p[1];
int *pInd = &p[2];
int nC = nCount >> 2;
while (nC)
{
Exchange(ar[pInd[0]], ar[pInd[1]]);
Exchange(ar[pInd[2]], ar[pInd[3]]);
Exchange(ar[pInd[4]], ar[pInd[5]]);
Exchange(ar[pInd[6]], ar[pInd[7]]);
pInd += 8;
nC--;
}
pInd = &p[2];
nC = nCount >> 2;
while (nC)
{
Exchange(ai[pInd[0]], ai[pInd[1]]);
Exchange(ai[pInd[2]], ai[pInd[3]]);
Exchange(ai[pInd[4]], ai[pInd[5]]);
Exchange(ai[pInd[6]], ai[pInd[7]]);
pInd += 8;
nC--;
}
}
void xcfft1dc(float* ar, float* ai, int *p, int nm)
{
cradix4c_64(ar, ai, nm);
cbitrevc(ar, ai, p);
}
void FFTSSE_64(float* ar, float* ai)
{
int i, j;
const int nm = 6;
_declspec(align(16)) int p0[OCEANGRID*8];
coef4r22c(p0, nm);
for (i=0; i<OCEANGRID; i++)
{
xcfft1dc(&ar[OCEANGRID*i], &ai[OCEANGRID*i], p0, nm);
}
coef4r22c(p0, nm);
_declspec(align(16)) float p1[4][OCEANGRID];
_declspec(align(16)) float p2[4][OCEANGRID];
float *src, *dst;
for (j=0; j<OCEANGRID; j+=4)
{
src = &ar[j];
for (i=0; i<OCEANGRID; i++, src+=OCEANGRID)
{
p1[0][i] = src[0];
p1[1][i] = src[1];
p1[2][i] = src[2];
p1[3][i] = src[3];
}
src = &ai[j];
for (i=0; i<OCEANGRID; i++, src+=OCEANGRID)
{
p2[0][i] = src[0];
p2[1][i] = src[1];
p2[2][i] = src[2];
p2[3][i] = src[3];
}
xcfft1dc(&p1[0][0], &p2[0][0], p0, nm);
xcfft1dc(&p1[1][0], &p2[1][0], p0, nm);
xcfft1dc(&p1[2][0], &p2[2][0], p0, nm);
xcfft1dc(&p1[3][0], &p2[3][0], p0, nm);
dst = &ar[j];
for (i=0; i<OCEANGRID; i++, dst+=OCEANGRID)
{
dst[0] = p1[0][i];
dst[1] = p1[1][i];
dst[2] = p1[2][i];
dst[3] = p1[3][i];
}
dst = &ai[j];
for (i=0; i<OCEANGRID; i++, dst+=OCEANGRID)
{
dst[0] = p2[0][i];
dst[1] = p2[1][i];
dst[2] = p2[2][i];
dst[3] = p2[3][i];
}
}
}
#pragma warning(pop)
#endif // !defined(WIN64)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,931 @@
/*=============================================================================
RenderPipeline.h : Shaders pipeline declarations.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#ifndef __RENDERPIPELINE_H__
#define __RENDERPIPELINE_H__
//====================================================================
#define PIPE_USE_INSTANCING
#define NUMRI_LISTS 6
#define MAX_HWINST_PARAMS 16384
typedef union UnINT64
{
uint64 SortVal;
struct
{
uint Low;
uint High;
}i;
} UnINT64;
struct SRendItemPre
{
UnINT64 SortVal;
CRendElement *Item;
union
{
uint ObjSort;
float fDist;
};
uint DynLMask;
};
struct SRendItemLight : SRendItemPre
{
};
struct SRendItemStenc : SRendItemPre
{
};
struct SRendItem : SRendItemPre
{
static void mfCalcRefractVectors(int Type, byte *Dst, int StrDst);
static void mfCalcLightAttenuation(int type, byte *Dst, int StrideDst);
static void mfCalcProjectVectors(int Type, float *Mat, float RefractIndex, byte *Dst, int StrDst);
static void mfCalcLightVectors(byte *lv, int Stride);
static void mfCalcNormLightVectors(byte *lv, int Stride, int Type);
static void mfCalcHalfAngles(int type, byte *ha, int StrHA);
static void mfCalcProjectAttenFromCamera(byte *dst, int Str);
static void mfCalcLAttenuationSpec0(byte *dst, int StrDst, byte *lv, int StrLV, int type);
static void mfCalcLAttenuationSpec1(byte *dst, int StrDst, byte *lv, int StrLV, int type);
static void mfCalcLightVectors_Terrain(byte *lv, int Stride);
static void mfCalcLAttenuationSpec0_Terrain(byte *dst, int StrDst, byte *lv, int StrLV, int type);
static void mfCalcLAttenuationSpec1_Terrain(byte *dst, int StrDst, byte *lv, int StrLV, int type);
static void mfCalcHalfAngles_Terrain(int type, byte *ha, int StrHA);
static void mfCalcTangentSpaceVectors();
static void mfComputeTangent(const Vec3d& v0, const Vec3d& v1, const Vec3d& v2, const float t0[2], const float t1[2], const float t2[2], Vec3d &tangent, Vec3d& binormal, float& sign, Vec3d& face_normal);
//==================================================
static void *mfGetPointerCommon(ESrcPointer ePT, int *Stride, int Type, ESrcPointer Dst, int Flags);
#ifdef PIPE_USE_INSTANCING
static _inline void mfAdd(CRendElement *Item, CCObject *pObj, SShader *Shader, int ResId, SShader *EfState, int numFog, int nTempl, int nSort=0)
{
int nList = nSort>>28;
nSort &= 0xffff;
int n = m_RendItems[nList].Num();
m_RendItems[nList].AddIndex(1);
SRendItemPre *ri = &m_RendItems[nList][n];
int IdState = EfState ? EfState->m_Id : 0;
nSort = (nSort > 0) ? nSort : Shader->m_eSort;
int ObjNum;
if (pObj)
{
ObjNum = pObj->m_VisId;
ri->ObjSort = (pObj->m_ObjFlags & 0xffff0000) | pObj->m_nLMId;
ri->DynLMask = pObj->m_DynLMMask;
}
else
{
ObjNum = 0;
ri->ObjSort = 0;
ri->DynLMask = 0;
}
ri->SortVal.i.Low = (ObjNum<<20) | (IdState<<8) | (numFog);
ri->SortVal.i.High = (nSort<<26) | (Shader->m_Id<<14) | (ResId);
ri->Item = Item;
}
static _inline void mfGet(UnINT64 flag, int *nObject, SShader **Shader, SShader **ShaderState, int *numFog, SRenderShaderResources **Res)
{
*numFog = flag.i.Low & 0x3f;
*Shader = SShader::m_Shaders_known[(flag.i.High>>14) & 0xfff];
int n = (flag.i.Low>>8) & 0xfff;
*ShaderState = n ? SShader::m_Shaders_known[n] : NULL;
*nObject = (flag.i.Low>>20) & 0xfff;
n = flag.i.High & 0x3fff;
*Res = (n) ? SShader::m_ShaderResources_known[n] : NULL;
}
static _inline void mfGetObj(UnINT64 flag, int *nObject)
{
*nObject = (flag.i.Low>>20) & 0xfff;
}
static _inline void mfGet(UnINT64 flag, SShader **Shader, SShader **ShaderState, SRenderShaderResources **Res)
{
*Shader = SShader::m_Shaders_known[(flag.i.High>>14) & 0xfff];
int n = (flag.i.Low>>8) & 0xfff;
*ShaderState = n ? SShader::m_Shaders_known[n] : NULL;
n = flag.i.High & 0x3fff;
*Res = (n) ? SShader::m_ShaderResources_known[n] : NULL;
}
static _inline SShader *mfGetShader(UnINT64 flag)
{
return SShader::m_Shaders_known[(flag.i.High>>14) & 0xfff];
}
#else
static _inline void mfAdd(CRendElement *Item, CCObject *pObj, SShader *Shader, int ResId, SShader *EfState, int numFog, int nTempl, int nSort=0)
{
int nList = nSort>>28;
nSort &= 0xffff;
int n = m_RendItems[nList].Num();
m_RendItems[nList].AddIndex(1);
SRendItemPre *ri = &m_RendItems[nList][n];
int IdState = EfState ? EfState->m_Id : 0;
nSort = (nSort > 0) ? nSort : Shader->m_eSort;
int ObjNum = pObj ? pObj->m_VisId : 0;
ri->SortVal.i.Low = (Shader->m_Id<<20) | (IdState<<8) | (numFog);
ri->SortVal.i.High = (nSort<<26) | (ObjNum<<15) | (ResId);
ri->Item = Item;
}
static _inline void mfGet(UnINT64 flag, int *nObject, SShader **Shader, SShader **ShaderState, int *numFog, SRenderShaderResources **Res)
{
*numFog = flag.i.Low & 0x3f;
*Shader = SShader::m_Shaders_known[(flag.i.Low>>20) & 0xfff];
int n = (flag.i.Low>>8) & 0xfff;
*ShaderState = n ? SShader::m_Shaders_known[n] : NULL;
*nObject = (flag.i.High>>15) & 0x7ff;
n = flag.i.High & 0x3fff;
*Res = (n) ? SShader::m_ShaderResources_known[n] : NULL;
}
static _inline void mfGet(UnINT64 flag, SShader **Shader, SShader **ShaderState, SRenderShaderResources **Res)
{
*Shader = SShader::m_Shaders_known[(flag.i.Low>>20) & 0xfff];
int n = (flag.i.Low>>8) & 0xfff;
*ShaderState = n ? SShader::m_Shaders_known[n] : NULL;
n = flag.i.High & 0x3fff;
*Res = (n) ? SShader::m_ShaderResources_known[n] : NULL;
}
#endif
// Sort by SortVal member of RI
static void mfSort(SRendItemPre *First, int Num);
// Special Sorting ignoring shadow maps
static void mfSortForStencil(SRendItemPre *First, int Num);
// Sort by distance
static void mfSortByDist(SRendItemPre *First, int Num);
// Sort by light
static void mfSortByLight(SRendItemPre *First, int Num);
static int m_RecurseLevel;
static int m_StartRI[8][NUMRI_LISTS];
static int m_EndRI[8][NUMRI_LISTS];
static TArray<SRendItemPre> m_RendItems[];
};
struct SRendItemPreprocess : public SRendItem
{
CCObject *m_Object;
static void mfSort(SRendItemPreprocess *First, int Num);
};
struct SRefSprite
{
CCObject *m_pObj;
};
//==================================================================
#define RNF_NOSHINE 0x1000
struct SMRendVert;
struct SMRendTexVert;
struct SShaderPass;
struct SEvalFuncs;
union UPipeVertex
{
void *Ptr;
byte *PtrB;
float *PtrF;
Vec3d *VBPtr_0;
struct_VERTEX_FORMAT_P3F *VBPtr_1;
struct_VERTEX_FORMAT_P3F_COL4UB *VBPtr_2;
struct_VERTEX_FORMAT_P3F_TEX2F *VBPtr_3;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *VBPtr_4;
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *VBPtr_5;
struct_VERTEX_FORMAT_P3F_COL4UB_COL4UB *VBPtr_6;
struct_VERTEX_FORMAT_P3F_N *VBPtr_7;
struct_VERTEX_FORMAT_P3F_N_COL4UB *VBPtr_8;
struct_VERTEX_FORMAT_P3F_N_TEX2F *VBPtr_9;
struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F *VBPtr_10;
SPipTangents *VBPtr_11;
struct_VERTEX_FORMAT_TEX2F *VBPtr_12;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F *VBPtr_13;
};
//==================================================================
#define MAX_DYNVBS 8
struct SMFenceBufs
{
uint m_Fence;
UPipeVertex Ptr;
CVertexBuffer *m_pVBDyn;
int m_nOffs;
int m_nCount;
};
//==================================================================
#define MAX_PORTAL_RECURSES 4
#define MAX_WARPSURFS 64
#define MAX_WARPS 8
struct SWarpSurf
{
CRendElement *srf;
int nobj;
SShader *Shader;
SRenderShaderResources *ShaderRes;
};
struct STWarpZone
{
Plane plane;
int numSrf;
SWarpSurf Surfs[MAX_WARPSURFS];
};
//==================================================================
// StencilStates
#define FSS_STENCFUNC_ALWAYS 0x0
#define FSS_STENCFUNC_NEVER 0x1
#define FSS_STENCFUNC_LESS 0x2
#define FSS_STENCFUNC_LEQUAL 0x3
#define FSS_STENCFUNC_GREATER 0x4
#define FSS_STENCFUNC_GEQUAL 0x5
#define FSS_STENCFUNC_EQUAL 0x6
#define FSS_STENCFUNC_NOTEQUAL 0x7
#define FSS_STENCFUNC_MASK 0x7
#define FSS_STENCIL_TWOSIDED 0x8
#define FSS_CCW_SHIFT 16
#define FSS_STENCOP_KEEP 0x0
#define FSS_STENCOP_REPLACE 0x1
#define FSS_STENCOP_INCR 0x2
#define FSS_STENCOP_DECR 0x3
#define FSS_STENCOP_ZERO 0x4
#define FSS_STENCOP_INCR_WRAP 0x5
#define FSS_STENCOP_DECR_WRAP 0x6
#define FSS_STENCFAIL_SHIFT 4
#define FSS_STENCFAIL_MASK (0x7 << FSS_STENCFAIL_SHIFT)
#define FSS_STENCZFAIL_SHIFT 8
#define FSS_STENCZFAIL_MASK (0x7 << FSS_STENCZFAIL_SHIFT)
#define FSS_STENCPASS_SHIFT 12
#define FSS_STENCPASS_MASK (0x7 << FSS_STENCPASS_SHIFT)
#define STENC_FUNC(op) (op)
#define STENC_CCW_FUNC(op) (op << FSS_CCW_SHIFT)
#define STENCOP_FAIL(op) (op << FSS_STENCFAIL_SHIFT)
#define STENCOP_ZFAIL(op) (op << FSS_STENCZFAIL_SHIFT)
#define STENCOP_PASS(op) (op << FSS_STENCPASS_SHIFT)
#define STENCOP_CCW_FAIL(op) (op << (FSS_STENCFAIL_SHIFT+FSS_CCW_SHIFT))
#define STENCOP_CCW_ZFAIL(op) (op << (FSS_STENCZFAIL_SHIFT+FSS_CCW_SHIFT))
#define STENCOP_CCW_PASS(op) (op << (FSS_STENCPASS_SHIFT+FSS_CCW_SHIFT))
//==================================================================
#ifdef DIRECT3D9
#include <d3d9.h>
#endif
#if defined (DIRECT3D8) || defined (DIRECT3D9)
template <class IndexType> class DynamicIB;
struct SD3DFixedVShader
{
#ifdef DIRECT3D8
TArray<DWORD> m_Declaration;
#elif DIRECT3D9
TArray<D3DVERTEXELEMENT9> m_Declaration;
LPDIRECT3DVERTEXDECLARATION9 m_pDeclaration;
#endif
DWORD m_Handle;
};
#endif
#if defined (DIRECT3D8) || defined (DIRECT3D9)
#define MAX_DYNVBS 8
template < class VertexType > class DynamicVB;
union UDynamicVB
{
DynamicVB <Vec3d> *VBPtr_0;
DynamicVB <struct_VERTEX_FORMAT_P3F> *VBPtr_1;
DynamicVB <struct_VERTEX_FORMAT_P3F_COL4UB> *VBPtr_2;
DynamicVB <struct_VERTEX_FORMAT_P3F_TEX2F> *VBPtr_3;
DynamicVB <struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F> *VBPtr_4;
DynamicVB <struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F> *VBPtr_5;
DynamicVB <struct_VERTEX_FORMAT_P3F_COL4UB_COL4UB> *VBPtr_6;
DynamicVB <struct_VERTEX_FORMAT_P3F_N> *VBPtr_7;
DynamicVB <struct_VERTEX_FORMAT_P3F_N_COL4UB> *VBPtr_8;
DynamicVB <struct_VERTEX_FORMAT_P3F_N_TEX2F> *VBPtr_9;
DynamicVB <struct_VERTEX_FORMAT_P3F_N_COL4UB_TEX2F> *VBPtr_10;
DynamicVB <SPipTangents> *VBPtr_11;
DynamicVB <struct_VERTEX_FORMAT_TEX2F> *VBPtr_12;
DynamicVB <struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F> *VBPtr_13;
};
struct SVertexDeclaration
{
int StreamMask;
int VertFormat;
int InstMask;
TArray<D3DVERTEXELEMENT9> m_Declaration;
LPDIRECT3DVERTEXDECLARATION9 m_pDeclaration;
};
#endif
struct SProfInfo
{
int NumPolys;
SShader *ef;
double Time;
int m_nItems;
};
struct SVrect
{
int x,y,width,height;
};
struct SPlane
{
byte m_Type;
byte m_SignBits;
Vec3d m_Normal;
float m_Dist;
void Init()
{
if ( m_Normal[0] == 1.0f )
m_Type = PLANE_X;
if ( m_Normal[1] == 1.0f )
m_Type = PLANE_Y;
if ( m_Normal[2] == 1.0f )
m_Type = PLANE_Z;
else
m_Type = PLANE_NON_AXIAL;
// for fast box on planeside test
int bits = 0;
int j;
for (j=0; j<3; j++)
{
if (m_Normal[j] < 0)
bits |= 1<<j;
}
m_SignBits = bits;
}
};
struct SStatItem
{
int m_Nums;
double m_fTime;
};
#define STARTPROFILE(Item) { ticks(Item.m_fTime); Item.m_Nums++; }
#define ENDPROFILE(Item) { unticks(Item.m_fTime); }
struct SPipeStat
{
int m_NumRendBatches;
int m_NumRendItems;
int m_NumRendObjects;
int m_NumDrawCalls;
int m_NumTextChanges;
int m_NumStateChanges;
int m_NumRendSkinnedObjects;
int m_NumLitShaders;
int m_NumVShadChanges;
int m_NumPShadChanges;
int m_NumVShaders;
int m_NumPShaders;
int m_NumTextures;
int m_TexturesSize;
int m_MeshUpdateBytes;
float m_fOverdraw;
float m_fSkinningTime;
float m_fPreprocessTime;
float m_fFlushTime;
float m_fTexUploadTime;
float m_fOcclusionTime;
int m_NumNotFinishFences;
int m_NumFences;
float m_fEnvCMapUpdateTime;
};
struct STexStageInfo
{
int nMipFilter;
byte Repeat;
byte Projected;
int MagFilter;
int MinFilter;
int Anisotropic;
int TCIndex;
// Per-stage color operations
byte m_CO;
byte m_CA;
byte m_AO;
byte m_AA;
#ifndef _XBOX
int Palette;
#else
void* Palette;
#endif
STexPic *Texture;
STexStageInfo()
{
Flush();
}
void Flush()
{
TCIndex = -1;
nMipFilter = -1;
Repeat = (bool)-1;
Anisotropic = 255;
Texture = NULL;
#ifndef _XBOX
Palette = -1;
#else
Palette = NULL;
#endif
}
};
struct SSplash
{
int m_Id;
Vec3d m_Pos;
float m_fForce;
eSplashType m_eType;
float m_fStartTime;
float m_fLastTime;
float m_fCurRadius;
};
// m_RP.m_Flags
#define RBF_2D 0x10
#define RBF_USEFENCES 0x100
#define RBF_MODIF_TC 0x1000
#define RBF_MODIF_VERT 0x2000
#define RBF_MODIF_COL 0x4000
#define RBF_MODIF_MASK 0xf000
#define RBF_NEAREST 0x10000
#define RBF_3D 0x40000
#define RBF_SHOWLINES 0x80000
// m_RP.m_PersFlags
#define RBPF_DONTDRAWSUN 1
#define RBPF_SETCLIPPLANE 2
#define RBPF_USESTREAM1 4
#define RBPF_USESTREAM2 8
#define RBPF_MEASUREOVERDRAW 0x10
#define RBPF_DONTDRAWNEAREST 0x20
#define RBPF_DRAWPORTAL 0x40
#define RBPF_DRAWMIRROR 0x80
#define RBPF_NOSHINE 0x100
#define RBPF_NOCLEARBUF 0x400
#define RBPF_DRAWNIGHTMAP 0x800
#define RBPF_DRAWHEATMAP 0x1000
#define RBPF_DRAWMOTIONMAP 0x2000
#define RBPF_DRAWSCREENMAP 0x4000
#define RBPF_MATRIXNOTLOADED 0x8000
#define RBPF_DRAWSCREENTEXMAP 0x10000 // tiago: added
#define RBPF_ONLYREFRACTED 0x20000
#define RBPF_IGNORERENDERING 0x40000
#define RBPF_IGNOREREFRACTED 0x80000
#define RBPF_PS1WASSET 0x100000
#define RBPF_PS2WASSET 0x200000
#define RBPF_VSWASSET 0x400000
#define RBPF_TSWASSET 0x800000
#define RBPF_PS1NEEDSET 0x1000000
#define RBPF_PS2NEEDSET 0x2000000
#define RBPF_VSNEEDSET 0x4000000
#define RBPF_TSNEEDSET 0x8000000
#define RBPF_WASWORLDSPACE 0x10000000
#define RBPF_MAKESPRITE 0x20000000
#define RBPF_MULTILIGHTS 0x40000000
#define RBPF_HDR 0x80000000
// m_RP.m_FlagsModificators
#define RBMF_TANGENTSUSED SHPF_TANGENTS
#define RBMF_LMTCUSED SHPF_LMTC
#define RBMF_BENDINFOUSED 4
#define RBMF_OBJUSESROTATE 8
// Texture transform flags (4)
#define RBMF_TCM0 0x100
// Object linear texgen flags (4)
#define RBMF_TCGOL0 0x1000
// Reflection map texgen flags (4)
#define RBMF_TCGRM0 0x10000
// Normal map texgen flags (4)
#define RBMF_TCGNM0 0x100000
// Normal map texgen flags (4)
#define RBMF_TCGSM0 0x1000000
#define RBMF_NOUPDATE 0x10000000
#define RBMF_TCG 0xffff000
#define RBMF_TCM 0xf00
// m_RP.m_FlagsPerFlush
#define RBSI_BLEND 0x1
#define RBSI_NOCULL 0x2
#define RBSI_WASDEPTHWRITE 0x4
#define RBSI_DRAWAS2D 0x8
#define RBSI_ALPHABLEND 0x10
#define RBSI_ALPHATEST 0x20
#define RBSI_DEPTHWRITE 0x40
#define RBSI_FOGVOLUME 0x80
#define RBSI_TEXSTATE 0x100
#define RBSI_ALPHAGEN 0x200
#define RBSI_RGBGEN 0x400
#define RBSI_COLORMASK 0x800
#define RBSI_INDEXSTREAM 0x1000
#define RBSI_USEVP 0x2000
#define RBSI_DEPTHTEST 0x4000
#define RBSI_DEPTHFUNC 0x8000
#define RBSI_SHADOWPASS 0x10000
#define RBSI_STENCIL 0x20000
#define RBSI_GLOBALRGB 0x40000
#define RBSI_GLOBALALPHA 0x80000
#define RBSI_VERTSMERGED 0x100000
#define RBSI_LMTCMERGED 0x200000
#define RBSI_TANGSMERGED 0x400000
#define RBSI_FURPASS 0x800000
#define RBSI_MERGED 0x1000000
#define RBSI_USE_LM 0x2000000
#define RBSI_USE_HDRLM 0x4000000
#define RBSI_USE_3DC 0x8000000
#define RBSI_USE_3DC_A 0x10000000
#define RBSI_USE_SPECANTIALIAS 0x20000000
// m_RP.m_HWCurState
// m_RP.m_HWPrevState
#define RPHW_VPROGRAM 1
#define RPHW_RCOMBINER 2
#define RPHW_PSHADER 4
// m_RP.m_ShaderLightMask
#define SLMF_DIRECT 0
#define SLMF_POINT 1
#define SLMF_PROJECTED 2
#define SLMF_TYPE_MASK (SLMF_POINT | SLMF_PROJECTED)
#define SLMF_ONLYSPEC 4
#define SLMF_SPECOCCLUSION 8
#define SLMF_LTYPE_SHIFT 16
struct SLightPass
{
CDLight *pLights[4];
int nLights;
int nProjectors;
};
// Render status structure
struct SRenderPipeline
{
SShader *m_pShader;
CCObject *m_pCurObject;
SShader *m_pStateShader;
CRendElement *m_pRE;
SRenderShaderResources *m_pShaderResources;
CCObject *m_pPrevObject;
#ifdef PIPE_USE_INSTANCING
TArray<CCObject *> m_MergedObjects;
TArray<CCObject *> m_RotatedMergedObjects;
TArray<CCObject *> m_NonRotatedMergedObjects;
#endif
int m_FrameGTC;
SGenTC *m_pGTC[MAX_TMU];
STexStageInfo m_TexStages[MAX_TMU];
short m_TransformFrame;
UCol m_CurGlobalColor;
UCol m_NeedGlobalColor;
SEvalFuncs *m_pCurFuncs;
SEvalFuncs_RE m_EvalFuncs_RE;
SEvalFuncs_C m_EvalFuncs_C;
float m_RealTime;
int m_ObjFlags;
int m_Flags; // Reset on start pipeline
int m_PersFlags; // Never reset
int m_FlagsPerFlush;
int m_FlagsModificators;
int m_FrameObject;
float m_fCurSpecShininess;
CName m_Name_SpecularExp;
int m_ClipPlaneEnabled;
CCObject *m_pIgnoreObject;
bool m_bStartPipeline;
bool m_bDrawToTexture;
int m_MirrorClipSide;
int m_RenderFrame;
int m_RendPass;
int m_ResourceState;
SEnvTexture *m_pCurEnvTexture;
int m_StatNumLights;
int m_StatNumLightPasses;
int m_StatNumPasses;
int m_StatLightMask;
char *m_ExcludeShader;
char *m_ShowOnlyShader;
TArray<SProfInfo> m_Profile;
Vec3d m_ViewOrg;
int m_CurrentVLightFlags;
int m_EnabledVLightFlags;
int m_EnabledVLights;
int m_CurrentVLights;
int m_ShaderLightMask;
int m_DynLMask;
CDLight *m_pCurLight;
int m_nCurLight;
int m_nCurLightPass;
int m_NumActiveDLights;
CDLight *m_pActiveDLights[16];
int m_nCurLightParam;
SLightPass m_LPasses[32];
SLightMaterial *m_pCurLightMaterial;
SLightMaterial m_DefLightMaterial;
SLightIndicies *m_pCurLightIndices;
SLightIndicies m_FakeLightIndices;
UPipeVertex m_Ptr;
UPipeVertex m_NextPtr;
int m_Stride;
int m_OffsT;
int m_OffsD;
int m_OffsN;
int m_CurVFormat;
TArray<CREOcLeaf *> m_MergedREs;
TArray<CCObject *> m_MergedObjs;
float m_fLastWaterFOVUpdate;
Vec3d m_LastWaterAngleUpdate;
Vec3d m_LastWaterPosUpdate;
float m_fLastWaterUpdate;
#if defined (DIRECT3D8) || defined (DIRECT3D9)
UDynamicVB m_VBs[MAX_DYNVBS];
DynamicIB <ushort> *m_IndexBuf;
UDynamicVB m_MergedStreams[3];
int m_nStreamOffset[3];
SD3DFixedVShader m_D3DFixedPipeline[8][VERTEX_FORMAT_NUMS];
DynamicVB <vec4_t> *m_VB_Inst;
TArray<SVertexDeclaration *>m_CustomVD;
#endif
ushort *m_RendIndices;
ushort *m_SysRendIndices;
int m_CurVB;
#ifdef OPENGL
int m_NumFences;
int m_CurFence;
int m_FenceCount;
SMFenceBufs m_VidBufs[MAX_DYNVBS];
SVertexStream m_IBDyn;
int m_IBDynOffs;
int m_IBDynSize;
int m_MergedStreams[3];
int m_nStreamOffset[3];
#endif
int m_RendNumIndices;
int m_RendNumVerts;
int m_FirstIndex;
int m_FirstVertex;
int m_BaseVertex;
int m_VFormatsMerge[VERTEX_FORMAT_NUMS][VERTEX_FORMAT_NUMS];
ECull m_eCull;
void (*m_pRenderFunc)();
SMFog *m_pFogVolume;
bool m_bClipPlaneRefract;
SPlane m_CurClipPlane;
SPlane m_CurClipPlaneCull;
int m_ClipPlaneWasOverrided;
int m_nClipPlaneTMU;
int m_FT;
SEfResTexture *m_ShaderTexResources[MAX_TMU];
CVProgram *m_CurVP;
CPShader *m_CurPS;
CVProgram *m_LastVP;
CPShader *m_RCSun;
CPShader *m_RCDetail;
CPShader *m_RCSprites;
CPShader *m_RCSprites_Heat;
CPShader *m_RCSprites_FV;
CVProgram *m_VPDetail;
CVProgram *m_VPTransformTexture;
CVProgram *m_VPTexShadow;
CVProgram *m_VPFog;
CPShader *m_RCFog;
CPShader *m_RCTexShadow;
CVProgram *m_VPPlantBendingSpr;
CVProgram *m_VPPlantBendingSpr_FV;
CPShader *m_RCBlur;
CVProgram *m_VPBlur;
CVProgram *m_VPSubSurfaceScatering;
CPShader *m_RCSubSurfaceScatering;
CVProgram *m_VPSubSurfaceScatering_pp;
CPShader *m_RCSubSurfaceScatering_pp;
CVProgram *m_VPFur_NormGen;
CVProgram *m_VPFur_OffsGen;
CPShader *m_RCFur_NormGen;
CPShader *m_RCFur_OffsGen;
CVProgram *m_VP_BaseCol;
CPShader *m_PS_HDRTemp;
CPShader *m_PS_HDRDownScale2x2;
CPShader *m_PS_HDRDownScale4x4;
CPShader *m_PS_HDRDownScale4x4_RG;
CPShader *m_PS_HDRDownScale4x4_BA;
CPShader *m_PS_HDRSampleAvgLum;
CPShader *m_PS_HDRResampleAvgLum;
CPShader *m_PS_HDRResampleAvgLumExp;
CPShader *m_PS_HDRCalcAdaptedLum;
CPShader *m_PS_HDRBrightPassFilter;
CPShader *m_PS_HDRGaussBlur5x5;
CPShader *m_PS_HDRGaussBlur5x5_Bilinear;
CPShader *m_PS_HDRBloom;
CPShader *m_PS_HDRStar;
CPShader *m_PS_HDRStar_MRT;
CPShader *m_PS_HDRFinalScene;
CPShader *m_PS_HDRMergeTextures[8];
CPShader *m_PS_HDR_ShowR;
CPShader *m_PS_HDR_ShowRG_MRT;
CPShader *m_PS_HDR_Base;
CPShader *m_PS_HDR_BaseCol;
CPShader *m_PS_HDR_BaseCol_FV;
CPShader *m_PS_HDR_AmbBase;
CPShader *m_PS_HDR_AmbBaseCol;
CPShader *m_PS_HDR_AmbBaseConst;
CPShader *m_PS_HDR_BaseConst;
CPShader *m_PS_HDR_AmbBaseCol_FV;
CPShader *m_PS_HDR_DrawFlare;
CPShader *m_PS_HDR_SkyFake;
CPShader *m_PS_HDR_Sky;
CPShader *m_PS_HDR_ClearScreen;
CPShader *m_PS_GaussBlurSep;
CVProgram *m_VS_GaussBlurSep;
SShaderPass *m_CurrPass;
int m_nCurStartCaster;
int m_Frame;
int m_FillFrame;
SShaderTechnique *m_pCurTechnique;
float m_fDistanceToCameraSquared;
float m_fCurOpacity;
Matrix44 m_WaterProjMatrix;
Vec3d m_CamVecs[3];
Vec3d m_OSCameraPos;
SPipeStat m_PS;
Vec3d m_SunDir;
CFColor m_SunColor;
int m_nLMStage;
INT_PTR m_nCurBufferID; // For ATI vertex object support //AMD Port
int m_nCurBufferOffset; // For ATI vertex object support
int m_MaxVerts;
int m_MaxTris;
int m_RECustomTexBind[8];
CFColor m_REColor;
float m_RECustomData[64];
STexPic *m_AnimTexs[4][32];
int m_CurLayerNum;
Vec3d m_Center;
CCamera m_PrevCamera;
//=========================================================================
// Per vertex attributes
Vec3d *m_pBinormals;
Vec3d *m_pTangents;
Vec3d *m_pTNormals;
Vec3d *m_pLightVectors[4];
Vec3d *m_pHalfAngleVectors[4];
Vec3d *m_pAttenuation;
Vec3d *m_pLAttenSpec0;
Vec3d *m_pLAttenSpec1;
SMRendTexVert *m_pBaseTexCoordPointer;
SMRendTexVert *m_pLMTexCoordPointer;
float *m_pFogVertValues;
bvec4 *m_pClientColors;
//===================================================================
// Input render data
TArray<SSplash> m_Splashes;
int m_NumVisObjects;
CCObject **m_VisObjects;
TArray<CDLight *> m_DLights[8];
TArray <CCObject *> m_RejectedObjects;
TArray <CCObject *> m_Objects;
TArray <CCObject *> m_TempObjects;
TArray<SMFog> m_FogVolumes;
CCObject *m_ObjectsPool;
int m_nNumObjectsInPool;
//================================================================
// Portals support
float m_fMinDepthRange;
float m_fMaxDepthRange;
int m_RecurseLevel;
int m_WasPortals;
int m_CurPortal;
STWarpZone *m_CurWarp;
//================================================================
// Sprites
TArray<SRefSprite> m_Sprites;
//================================================================
// Temporary mesh
TArray<class CRETempMesh *> m_TempMeshes[2];
TArray<class CRETempMesh *> *m_CurTempMeshes;
//================================================================
// Glare Heat and Night
class CREGlare *m_pREGlare;
class CREHDRProcess *m_pREHDR;
int m_HeatSize;
int m_NightSize;
int m_GlareSize;
int m_RainMapSize;
int m_FlashBangSize;
//=================================================================
// WaveForm tables
float m_tSinTable[1024];
float m_tHalfSinTable[1024];
float m_tCosTable[1024];
float m_tSquareTable[1024];
float m_tTriTable[1024];
float m_tSawtoothTable[1024];
float m_tInvSawtoothTable[1024];
float m_tHillTable[1024];
float m_tRandFloats[256];
byte m_tRandBytes[256];
};
#define MAX_REND_OBJECTS 4096
#endif // __RENDERPIPELINE_H__

File diff suppressed because it is too large Load Diff

1264
RenderDll/Common/Renderer.h Normal file

File diff suppressed because it is too large Load Diff

1099
RenderDll/Common/ResFile.cpp Normal file

File diff suppressed because it is too large Load Diff

245
RenderDll/Common/ResFile.h Normal file
View File

@@ -0,0 +1,245 @@
#ifndef __RESFILE_H__
#define __RESFILE_H__
#define IDRESHEADER (('K'<<24)+('C'<<16)+('P'<<8)+'C')
#define RESVERSION 1
enum EResId
{
eRI_UNKNOWN = -1,
eRI_BIN = 0,
eRI_IMAGE = 1,
eRI_MIPTEX = 2,
eRI_SOUND = 3,
eRI_MODEL = 4,
eRI_PALETTE = 5
};
enum EArc
{
eARC_NONE = 0,
eARC_RLE = 1,
eARC_LZSS = 2
};
// Resource header
struct SFileResHeader
{
uint hid;
int ver;
uint optimize_mode;
int num_files;
#ifdef PS2
int ofs_first;
#else
long ofs_first;
#endif
};
enum EFS_DirType
{
eFSD_name,
eFSD_id,
};
// Each file entry in resource
struct SFileDirEntry_0
{
char name[256-6*4];
int size;
int offset;
int offnext;
int offprev;
EResId eid; // eRI_
EArc earc; // eARC_
};
// Each file entry in resource
struct SFileDirEntry_1
{
int ID;
int size;
int offset;
int offnext;
int offprev;
EResId eid; // eRI_
EArc earc; // eARC_
};
struct SCacheUser
{
void *data;
};
// Intrinsic file entry
struct SDirEntry
{
uint ID;
int size;
#ifdef PS2
long offset;
long offsetHeader;
long curseek;
#else
int offset;
int offsetHeader;
int curseek;
#endif
EResId eid; // eRI_
EArc earc; // eARC_
SCacheUser user;
uint flags;
SDirEntry()
{
memset(this, 0, sizeof(SDirEntry));
}
const char *Name()
{
return CName(ID).c_str();
}
};
typedef std::map<uint,SDirEntry*> ResFilesMap;
typedef ResFilesMap::iterator ResFilesMapItor;
// Resource access types
#define RA_READ 1
#define RA_WRITE 2
#define RA_CREATE 4
// Resource files flags
#define RF_NOTSAVED 1
#define RF_DELETED 2
#define RF_INTRINSIC 4
#define RF_CACHED 8
#define RF_BIG 0x10
#define RF_TEMPDATA 0x20
// Resource optimize flags
#define RO_HEADERS_IN_BEGIN 1
#define RO_HEADERS_IN_END 2
#define RO_HEADER_FILE 4
#define RO_SORT_ALPHA_ASC 8
#define RO_SORT_ALPHA_DESC 0x10
#define MAX_OPEN_RESFILES 40
class CResFile
{
private:
char m_name[1024];
char *m_szAccess;
FILE* m_handle;
EFS_DirType m_eDT;
ResFilesMap m_dir;
int m_typeaccess;
uint m_optimize;
char m_ermes[1024];
int m_version;
int m_holesSize;
static CResFile m_Root;
static int m_nNumOpenResources;
CResFile *m_Next;
CResFile *m_Prev;
bool mfActivate(bool bFirstTime);
void mfDeactivate();
_inline void Relink(CResFile* Before)
{
if (m_Next && m_Prev)
{
m_Next->m_Prev = m_Prev;
m_Prev->m_Next = m_Next;
}
m_Next = Before->m_Next;
Before->m_Next->m_Prev = this;
Before->m_Next = this;
m_Prev = Before;
}
_inline void Unlink()
{
if (!m_Next || !m_Prev)
return;
m_Next->m_Prev = m_Prev;
m_Prev->m_Next = m_Next;
m_Next = m_Prev = NULL;
}
_inline void Link(CResFile* Before)
{
if (m_Next || m_Prev)
return;
m_Next = Before->m_Next;
Before->m_Next->m_Prev = this;
Before->m_Next = this;
m_Prev = Before;
}
public:
CResFile(const char* name, EFS_DirType eDT);
CResFile();
~CResFile();
char* mfGetError(void);
void mfSetError(const char *er);
const char *mfGetFileName() {return m_name;}
bool mfGetDir(TArray<SDirEntry *>& Dir);
bool mfOpen(int type);
bool mfClose();
bool mfFlush();
bool mfOptimize(uint type);
int mfGetNumFiles() { return m_dir.size(); }
int mfFileGetNum(const char* name);
int mfFileRead(SDirEntry *de);
int mfFileRead(const char* name);
int mfFileRead(int num);
int mfFileRead(SDirEntry *de, void* data);
int mfFileRead(int num, void* data);
int mfFileRead(const char* name, void* data);
void* mfFileRead2(SDirEntry *de, int size);
void* mfFileRead2(int num, int size);
void* mfFileRead2(const char* name, int size);
void mfFileRead2(SDirEntry *de, int size, void *buf);
void mfFileRead2(int num, int size, void *buf);
void* mfFileGetBuf(SDirEntry *de);
void* mfFileGetBuf(int num);
void* mfFileGetBuf(char* name);
int mfFileSeek(SDirEntry *de, int offs, int type);
int mfFileSeek(int num, int offs, int type);
int mfFileSeek(char* name, int offs, int type);
int mfFileLength(SDirEntry *de);
int mfFileLength(int num);
int mfFileLength(char* name);
int mfFileAdd(SDirEntry* de);
int mfFileDelete(SDirEntry *de);
int mfFileDelete(int num);
int mfFileDelete(char* name);
int mfFileExist(int ID);
int mfFileExist(const char* name);
SDirEntry *mfGetEntry(int num);
FILE *mfGetHandle() { return m_handle; }
int mfGetResourceSize();
int mfGetHolesSize();
};
#endif // __RESFILE_H__

View File

@@ -0,0 +1,408 @@
#ifndef __CSHADER_H__
#define __CSHADER_H__
#include <map>
struct SRenderBuf;
class CRendElement;
struct SEmitter;
struct SParticleInfo;
struct SPartMoveStage;
struct SSunFlare;
//===================================================================
#define MAX_ENVLIGHTCUBEMAPS 16
#define ENVLIGHTCUBEMAP_SIZE 16
#define MAX_ENVLIGHTCUBEMAPSCANDIST_UPDATE 16
#define MAX_ENVLIGHTCUBEMAPSCANDIST_THRESHOLD 2
#define MAX_ENVCUBEMAPS 4
#define MAX_ENVCUBEMAPSCANDIST_THRESHOLD 1
#define MAX_ENVTEXTURES 4
#define MAX_ENVTEXSCANDIST 0.1f
struct SNameAlias
{
CName m_Alias;
CName m_Name;
};
struct SEnvTexture
{
bool m_bInprogress;
bool m_bReady;
bool m_bWater;
bool m_bReflected;
int m_MaskReady;
int m_Id;
int m_TexSize;
// Result Cube-Map or 2D RT texture
STexPic *m_Tex;
// Temporary 2D texture
STexPic *m_TexTemp;
float m_TimeLastUsed;
Vec3d m_CamPos;
Vec3d m_ObjPos;
Vec3d m_Angle;
int m_nFrameReset;
// Cube maps average colors (used for RT radiosity)
int m_nFrameCreated[6];
UCol m_EnvColors[6];
void *m_RenderTargets[6];
};
//===================================================================
#define MAX_EF_FILES 256
struct SRegTemplate
{
char m_Name[64];
SShader *m_pShader;
};
#define SF_RELOAD 1
class CShader
{
friend struct SShader;
private:
void mfStartScriptPreprocess();
int mfRemoveScript_ifdef(char *posStart, char *posEnd, bool bRemoveAll, int nPos, char *buf, const char *fileName);
char *mfPreprCheckMacros (char *buf, const char *nameFile);
char *mfPreprCheckConditions (char *buf, const char *nameFile);
char *mfPreprCheckIncludes (char *buf, const char *drn, const char *name);
int mfLoadSubdir (char *drn, int n);
int mfReadTexSequence(SShader *ef, TArray<STexPic *>& txs, const char *name, byte eTT, int Flags, int Flags2, float fAmount1=-1.0f, float fAmount2=-1.0f);
SShader *mfNewShader(EShClass Class, int num);
char *mfRescanScript(int type, int nInd, SShader *pSHOrg, uint64 nMaskGen);
void mfScanScript (char *scr, int n);
bool mfCompileShaderGen(SShader *ef, SShaderGen *shg, char *scr);
SShaderGenBit *mfCompileShaderGenProperty(SShader *ef, char *scr);
SShader *mfCompileShader(SShader *ef, char *scr);
void mfCompileFogParms(SShader *ef, char *scr);
void mfCompileDeform(SShader *ef, SDeform *df, char *dname, char *scr);
bool mfCompileSunFlares(SShader *ef, char *name, char *scr);
bool mfCompileFlare(SShader *ef, SSunFlare *fl, char *scr);
bool mfCompileParams(SShader *ef, char *scr);
bool mfCompileRenderParams(SShader *ef, char *scr);
bool mfCompilePublic(SShader *ef, char *scr);
void mfParseLightStyle(CLightStyle *ls, char *lstr);
bool mfCompileLightStyle(SShader *ef, int num, char *scr);
void mfCompileParamComps(SParam *pr, char *scr, SShader *ef);
uint mfCompileRendState(SShader *ef, SShaderPass *sm, char *scr);
bool mfCompileSequence(SShader *ef, SShaderTexUnit *tl, int nLayer, char *scr, ETexType eTT, int Flags, int Flags2, float fBumpAmount);
void mfCompileOrient(SShader *ef, int num, char *scr);
void mfCompileLightMove(SShader *ef, char *nameMove, SLightEval *le, char *scr);
void mfCompileEvalLight(SShader *ef, char *scr);
void mfCompileStencil(SShader *ef, char *params);
void mfCompileState(SShader *ef, char *params);
STexPic *mfTryToLoadTexture(const char *nameTex, int Flags, int Flags2, byte eTT, SShader *sh, float fAmount1=-1.0f, float fAmount2=-1.0f);
STexPic *mfLoadResourceTexture(const char *nameTex, const char *path, int Flags, int Flags2, byte eTT, SShader *sh, SEfResTexture *Tex, float fAmount1=-1.0f, float fAmount2=-1.0f);
bool mfCheckAnimatedSequence(SShaderTexUnit *tl, STexPic *tx);
STexPic *mfCheckTemplateTexName(char *mapname, ETexType eTT, short &nFlags);
void mfCheckShaderResTextures(TArray<SShaderPass> &Dst, SShader *ef, SRenderShaderResources *Res);
void mfCheckShaderResTexturesHW(TArray<SShaderPassHW> &Dst, SShader *ef, SRenderShaderResources *Res);
int mfTemplateNameToId(char *name);
void mfCompileTemplate(SShader *ef, char *scr);
bool mfCompileTexGen(char *name, char *params, SShader *ef, SShaderTexUnit *ml);
SShader *mfCompile(SShader *ef, char *scr);
void mfCompileLayers(SShader *ef, char *scr, TArray<SShaderPassHW>& Layers, EShaderPassType eType);
void mfCompileVarsPak(char *scr, TArray<CVarCond>& Vars, SShader *ef);
void mfCompileHWConditions(SShader *ef, char *scr, SShaderTechnique *hs, int Id);
SShaderTechnique *mfCompileHW(SShader *ef, char *scr, int Id);
bool mfUpdateMergeStatus(SShaderTechnique *hs, TArray<SCGParam4f> *p);
bool mfCompileHWShadeLayer(SShader *ef, char *scr, TArray<SShaderPassHW>& Layers);
void mfClEfCompile(SShader *ef, char *scr, char *name);
bool mfReloadShaderScript(const char *szShaderName, int nFlags, SShader *pSH);
void mfRefreshResources(SShader *eft, SRenderShaderResources *Res);
bool mfAddTemplate(SRenderShaderResources *Res, SShader *ef, int IdTempl, const char *Name=NULL, uint64 nMaskGen=0);
void mfRegisterDefaultTemplates();
void mfUnregisterDefaultTemplates();
bool mfSetOpacity (SShaderPass *Layer, float Opa, SShader *ef, int Mode);
void mfRefreshLayer(SShaderPass *sl, SShader *sh);
bool mfReloadShader(const char *szName, int nFlags);
bool mfReloadShaderFile(const char *szName, int nFlags);
void mfCheckAffectedFiles(const char *ShadersPath, int nCheckFile, TArray<char *>& CheckNames, TArray<char *>& AffectedFiles);
public:
char *m_pCurScript;
ShaderMacro m_Macros;
TArray<SLocalMacros> m_LocalMacros;
bool PackCache();
SShaderCacheHeaderItem *GetCacheItem(SShaderCache *pCache, int nMask);
bool FreeCacheItem(SShaderCache *pCache, int nMask);
bool AddCacheItem(SShaderCache *pCache, SShaderCacheHeaderItem *pItem, byte *pData, int nLen, bool bFlush);
SShaderCache *OpenCacheFile(const char *szName, float fVersion);
bool FlushCacheFile(SShaderCache *pCache);
bool CloseCacheFile(SShaderCache *pCache);
char *mfScriptPreprocessor (char *buf, const char *drn, const char *name);
uint64 mfScriptPreprocessorMask(SShader *pSH, int nOffset);
bool mfReloadAllShaders(int nFlags);
bool mfReloadFile(const char *szPath, const char *szName, int nFlags);
const char *mfTemplateTexIdToName(int Id);
bool mfGetParmComps(int comp, SParam *vpp, char *name, char *params, SShader *ef);
bool mfCompilePlantsTMoving(char *scr, SShader *ef, TArray<SParam>* Params, int reg);
void mfCompileParamMatrix(char *scr, SShader *ef, SParamComp_Matrix *pcm);
bool mfCompileParam(char *scr, SShader *ef, TArray<SParam>* Params);
bool mfCompileCGParam(char *scr, SShader *ef, TArray<SCGParam4f>* Params);
void mfCheckObjectDependParams(TArray<SParam>* PNoObj, TArray<SParam>* PObj);
void mfCheckObjectDependParams(TArray<SCGParam4f>* PNoObj, TArray<SCGParam4f>* PObj);
void mfCompileArrayPointer(TArray<SArrayPointer *>& Pointers, char *scr, SShader *ef);
ESrcPointer mfParseSrcPointer(char *type, SShader *ef);
bool mfCompileLayer(SShader *ef, int num, char *scr, SShaderPass *sm);
bool mfRegisterTemplate(int nTemplId, char *Name, bool bReplace, bool bDefault=false);
void mfLoadFromFiles(int num);
void mfBeginFrame();
void mfCompileMatrixOp(TArray<SMatrixTransform>* MatrixOps, char *scr, char *name, SShader *ef);
SEnvTexture *mfFindSuitableEnvLCMap(Vec3d& Pos, bool bMustExist, int RendFlags, float fDistToCam, CCObject *pObj=NULL);
SEnvTexture *mfFindSuitableEnvCMap(Vec3d& Pos, bool bMustExist, int RendFlags, float fDistToCam);
SEnvTexture *mfFindSuitableEnvTex(Vec3d& Pos, Vec3d& Angs, bool bMustExist, int RendFlags, bool bUseExistingREs, SShader *pSH, SRenderShaderResources *pRes, CCObject *pObj, bool bReflect, CRendElement *pRE);
private:
ShaderFilesMap *m_RefEfs[2];
LoadedShadersMap m_RefEfsLoaded;
public:
bool m_bInitialized;
char m_ShadersPath[2][128];
char m_ShadersCache[128];
char *m_ModelsPath;
char *m_TexturesPath;
char *m_SystemPath;
char m_HWPath[128];
SOrient m_Orients[MAX_ORIENTS];
int m_NumOrients;
string m_FileNames[2][MAX_EF_FILES];
short m_nFrameReload[2][MAX_EF_FILES];
FILETIME m_WriteTime[2][MAX_EF_FILES];
int m_NumFiles[2];
int m_nFrameForceReload;
int m_NightMapReady;
int m_nCountNightMap;
int m_CurEfsNum;
SShader *m_CurShader;
TArray<SNameAlias> m_AliasNames;
TArray<SNameAlias> m_CustomAliasNames;
static SShader *m_DefaultShader;
#ifndef NULL_RENDERER
static SShader *m_ShaderVFog;
static SShader *m_ShaderVFogCaust;
static SShader *m_ShaderFog;
static SShader *m_ShaderFogCaust;
static SShader *m_ShaderFog_FP;
static SShader *m_ShaderFogCaust_FP;
static SShader *m_ShaderStateNoCull;
static SShader *m_ZBuffPassShader;
static SShader *m_ShadowMapShader;
static SShader *m_ShaderHDRProcess;
static SShader *m_GlareShader;
static SShader *m_ShaderSunFlares;
static SShader *m_ShaderLightStyles;
static SShader *m_ShaderCGPShaders;
static SShader *m_ShaderCGVProgramms;
#else
static SShaderItem m_DefaultShaderItem;
#endif
TArray<SRegTemplate> m_KnownTemplates;
int m_Frame;
SRenderShaderResources *m_pCurResources;
Matrix44 m_TempMatrices[4][8];
bool m_bReload;
int m_Nums;
int m_MaxNums;
int m_FirstCopyNum;
bool m_bNeedSysBuf;
bool m_bNeedCol;
bool m_bNeedSecCol;
bool m_bNeedNormal;
bool m_bNeedTangents;
int m_nTC;
public:
CShader()
{
m_bInitialized = false;
m_CurEfsNum = 0;
m_NumFiles[0] = m_NumFiles[1] = 0;
m_DefaultShader = NULL;
}
void mfShutdown (void);
void mfClearAll (void);
void mfClearShaders (TArray<SShader *> &Efs, int *Nums);
SShader *mfCopyShader(SShader *ef);
void mfCompileWaveForm(SWaveForm *wf, char *scr);
void mfCompileRGBAStyle(char *scr, SShader *ef, SShaderPass *sp, bool bRGB);
void mfCompileRGBNoise(SRGBGenNoise *cn, char *scr, SShader *ef);
void mfCompileAlphaNoise(SAlphaGenNoise *cn, char *scr, SShader *ef);
void mfAddToHash (char *Name, SShader *ef);
void mfAddToHashLwr (char *Name, SShader *ef);
void mfRemoveFromHash (SShader *ef);
//STexPic *mfLoadCubeTex(const char *mapname, uint flags, uint flags2, int State, ETexType eTT, int RState, int Id, int BindId=0);
int mfReadAllImgFiles(SShader *ef, SShaderTexUnit *tl, STexAnim *ta, char *name);
void mfInit(void);
void mfShaderNameForAlias(const char *nameAlias, char *nameEf, int nSize);
SRenderShaderResources *mfCreateShaderResources(const SInputShaderResources *Res, bool bShare);
SShaderItem mfShaderItemForName (const char *name, EShClass Class, bool bShare, const char *templName, int flags, const SInputShaderResources *Res=NULL, uint64 nMaskGen=0);
SShader *mfForName (const char *name, EShClass Class, int flags, const SInputShaderResources *Res=NULL, uint64 nMaskGen=0);
SShader *mfSpawn (char *name, SShader *ef, SShader *efGen, uint64 nMaskGen);
bool mfParseFXTechnique_MergeParameters (std::vector<SFXStruct>& Structs, std::vector<SFXParam>& Params, int nNum, SShader *ef, bool bPixelShader, const char *szShaderName);
bool mfParseFXTechnique_LoadShaderTexture (SFXSampler *smp, SFXTexture *tx, SShaderPassHW *pShPass, SShader *ef, int nIndex, byte ColorOp, byte AlphaOp, byte ColorArg, byte AlphaArg);
bool mfParseFXTechnique_LoadShader (const char *szShaderCom, SShaderPassHW *pShPass, SShader *ef, std::vector<SFXSampler>& Samplers, std::vector<SFXTexture>& Textures, std::vector<SFXStruct>& Structs, std::vector<SFXParam>& Params, std::vector<SPair>& Macros, bool bPixelShader);
bool mfParseFXTechniquePass (char *buf, char *annotations, SShaderTechnique *pShTech, SShader *ef, std::vector<SFXSampler>& Samplers, std::vector<SFXTexture>& Textures, std::vector<SFXStruct>& Structs, std::vector<SFXParam>& Params);
bool mfParseFXTechnique (char *buf, char *annotations, SShader *ef, std::vector<SFXSampler>& Samplers, std::vector<SFXTexture>& Textures, std::vector<SFXStruct>& Structs, std::vector<SFXParam>& Params);
bool mfParseFXSampler(char *buf, char *name, SShader *ef, std::vector<SFXSampler>& Samplers, std::vector<SFXTexture>& Textures);
SShader *mfParseFX (char *buf, SShader *ef, SShader *efGen, uint64 nMaskGen);
char *mfFindInAllText (char *name, char *&pBuf, SShader *shGen, uint64 nMaskGen);
char **mfListInScript (char *scr);
char *mfScriptForFileName(const char *name, SShader *shGen, uint64 nMaskGen);
void mfSetDefaults(void);
void mfOptimizeShader(SShader *ef, TArray<SShaderPass>& Layers, int Stage);
void mfOptimizeShaderHW(SShader *ef, TArray<SShaderPassHW>& Layers, int Stage);
void mfConstruct(SShader *ef);
#ifdef WIN64
#pragma warning( push ) //AMD Port
#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'XXX', possible loss of data
#endif
int Size()
{
int i, j;
int nSize = sizeof(*this);
nSize += m_KnownTemplates.GetMemoryUsage();
nSize += m_AliasNames.GetMemoryUsage();
for (i=0; i<2; i++)
{
for (j=0; j<MAX_EF_FILES; j++)
{
if (!m_FileNames[i][j].empty())
nSize += m_FileNames[i][j].capacity();
}
}
return nSize;
}
};
#ifdef WIN64
#pragma warning( pop ) //AMD Port
#endif
//=====================================================================
struct SSunFlare
{
float m_Scale;
float m_Loc; // position offset on axis
CFColor m_Color;
STexPic *m_Tex;
Vec3d m_Position;
float m_RenderSize;
int Size()
{
int nSize = sizeof(SSunFlare);
return nSize;
}
SSunFlare()
{
m_Tex = NULL;
m_Scale = 1.0f;
m_Loc = 0;
m_Color = Col_White;
}
~SSunFlare();
};
class CSunFlares
{
private:
public:
static TArray<CSunFlares *> m_SunFlares;
static CSunFlares *m_CurFlares;
char m_Name[32];
int m_NumFlares;
SSunFlare *m_Flares;
//==================================================================
int Size()
{
int nSize = sizeof(CSunFlares);
for (int i=0; i<m_NumFlares; i++)
{
nSize += m_Flares[i].Size();
}
return nSize;
}
static CSunFlares *mfForName(char *name);
CSunFlares()
{
m_NumFlares = 0;
m_Flares = NULL;
}
~CSunFlares()
{
if (m_Flares)
delete [] m_Flares;
m_NumFlares = 0;
}
};
//=====================================================================
#endif // __CSHADER_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/*=============================================================================
Parser.h : Script parser declarations.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#ifndef PARSER_H
#define PARSER_H
extern char *pCurCommand;
/**
* Structure to describe a single token
*/
typedef struct
{
/// value returned when token is matched
long id;
/// token to match
char *token;
} tokenDesc;
struct SFXTokenDesc
{
int id;
char *token;
};
extern const char *kWhiteSpace;
/// Get an object from the buffer.
long shGetObject(char **buf, tokenDesc *tokens, char **name, char **data);
/// Get a command from the buffer.
long shGetCommand(char **buf, tokenDesc *tokens, char **params);
extern std::vector<SPair> g_Macros;
long fxGetObject(char **buf, tokenDesc *tokens, char **name, char **data, int &nIndex);
long fxGetObject(char **buf, SFXTokenDesc *tokens, char **name, char **value, char **data, char **assign, char **annotations, std::vector<SFXStruct>& Structs);
void fxGetParams(char *annot, std::vector<SFXParam>& prms);
void fxParserInit(void);
void fxStart(void);
void fxIncrLevel();
void fxDecrLevel();
int fxFill(char **buf, char *dst);
void fxTranslate(char **buf);
char *fxGetAssignmentText(char **buf);
char *fxGetAssignmentText2(char **buf);
char *GetSubText(char **buf, char open, char close);
void SkipCharacters(char **buf, const char *toSkip);
char *GetAssignmentText(char **buf);
void SkipComments(char **buf, bool bSkipWhiteSpace);
char *RemoveComments(char *buf);
void RemoveCR(char *buf);
bool shGetBool(char *buf);
float shGetFloat(char *buf);
void shGetFloat(char *buf, float *v1, float *v2);
int shGetInt(char *buf);
int shGetHex(const char *buf);
uint64 shGetHex64(const char *buf);
void shGetVector(char *buf, Vec3d& v);
void shGetVector(char *buf, float v[3]);
void shGetVector4(char *buf, vec4_t& v);
void shGetColor(char *buf, CFColor& v);
void shGetColor(char *buf, float v[4]);
int shGetVar (char **buf, char **vr, char **val);
char *fxReplaceInText(char *pText, const char *pSubStr, const char *pReplace);
char *fxReplaceInText2(char *pText, const char *pSubStr, const char *pReplace);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,230 @@
#ifndef SHADOWMAP_H
#define SHADOWMAP_H
enum EShadowType
{
EST_DEPTH_BUFFER,
EST_2D_BUFFER,
EST_PENUMBRA
};
#include "IRenderer.h"
#define SMFF_ACTIVE_SHADOW_MAP 1
struct ShadowMapFrustum
{
float debugLightFrustumMatrix[16];
float debugLightViewMatrix[16];
unsigned int depth_tex_id;
struct ShadowMapLightSource * pLs;
EShadowType shadow_type;
float FOV;
float min_dist;
float max_dist;
Vec3d target;
bool bUpdateRequested;
int nDLightId;
int nTexSize;
ShadowMapFrustum * pPenumbra;
struct IEntityRender * pOwner;
IStatObj * pOwnerGroup;
int nTexIdSlot;
int nResetID;
int dwFlags;
float fAlpha;
float ProjRatio;
float fOffsetScale;
list2<struct IStatObj*> * pModelsList;
list2<struct IEntityRender*> * pEntityList;
Plane arrFrusrumPlanes[4];
float m_fCeachedFrustumScale;
int m_nCeachedFrustumFrameId;
float m_fBending;
ShadowMapFrustum()
{
ZeroStruct(*this);
nTexIdSlot = -1;
fAlpha = 1.f;
ProjRatio = 1.f;
nDLightId = -1;
fOffsetScale = 1.f;
}
~ShadowMapFrustum()
{
delete pModelsList;
delete pEntityList;
delete pPenumbra;
}
void UnProject(float sx, float sy, float sz, float *px, float *py, float *pz, IRenderer * pRend )
{
const int shadowViewport[4] = {0,0,1,1};
pRend->UnProject(sx,sy,sz,
px,py,pz,
debugLightViewMatrix,
debugLightFrustumMatrix,
shadowViewport);
}
Vec3d & UnProjectVertex3d(int sx, int sy, int sz, Vec3d & vert, IRenderer * pRend)
{
float px;
float py;
float pz;
UnProject((float)sx, (float)sy, (float)sz, &px, &py, &pz, pRend);
vert.x=(float)px;
vert.y=(float)py;
vert.z=(float)pz;
// pRend->DrawBall(vert,10);
return vert;
}
void DrawFrustum(IRenderer * pRend, Vec3d vPos, float fScale)
{
Vec3d vert1,vert2;
{
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(0,0,0,vert1,pRend),
vPos+fScale*UnProjectVertex3d(0,0,1,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(1,0,0,vert1,pRend),
vPos+fScale*UnProjectVertex3d(1,0,1,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(1,1,0,vert1,pRend),
vPos+fScale*UnProjectVertex3d(1,1,1,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(0,1,0,vert1,pRend),
vPos+fScale*UnProjectVertex3d(0,1,1,vert2,pRend), true);
}
for(int i=0; i<=1; i++)
{
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(0,0,i,vert1,pRend),
vPos+fScale*UnProjectVertex3d(1,0,i,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(1,0,i,vert1,pRend),
vPos+fScale*UnProjectVertex3d(1,1,i,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(1,1,i,vert1,pRend),
vPos+fScale*UnProjectVertex3d(0,1,i,vert2,pRend), true);
pRend->Draw3dBBox(
vPos+fScale*UnProjectVertex3d(0,1,i,vert1,pRend),
vPos+fScale*UnProjectVertex3d(0,0,i,vert2,pRend), true);
}
}
void InitFrustum(float fFrustumScale, IRenderer * pRend)
{
Vec3d v1,v2,v3;
// top
UnProjectVertex3d(0,0,0,v1,pRend),
UnProjectVertex3d(0,0,1,v2,pRend);
UnProjectVertex3d(1,0,1,v3,pRend);
arrFrusrumPlanes[0].Init(v1*fFrustumScale, v2*fFrustumScale, v3*fFrustumScale);
// left
UnProjectVertex3d(0,1,0,v1,pRend),
UnProjectVertex3d(0,1,1,v2,pRend);
UnProjectVertex3d(0,0,1,v3,pRend);
arrFrusrumPlanes[1].Init(v1*fFrustumScale, v2*fFrustumScale, v3*fFrustumScale);
// bottom
UnProjectVertex3d(1,1,0,v1,pRend),
UnProjectVertex3d(1,1,1,v2,pRend);
UnProjectVertex3d(0,1,1,v3,pRend);
arrFrusrumPlanes[2].Init(v1*fFrustumScale, v2*fFrustumScale, v3*fFrustumScale);
// right
UnProjectVertex3d(1,0,0,v1,pRend),
UnProjectVertex3d(1,0,1,v2,pRend);
UnProjectVertex3d(1,1,1,v3,pRend);
arrFrusrumPlanes[3].Init(v1*fFrustumScale, v2*fFrustumScale, v3*fFrustumScale);
}
bool IsSphereInsideFrustum(Vec3d vSphereCenter, float fSphereRadius, float fFrustumScale, IRenderer * pRend)
{
// todo: optimize this
static int a=0, b=0;
if(/*debugLightFrustumMatrix[0] && */m_fCeachedFrustumScale != fFrustumScale || m_nCeachedFrustumFrameId != pRend->GetFrameID())
{
InitFrustum(fFrustumScale, pRend);
m_fCeachedFrustumScale = fFrustumScale;
m_nCeachedFrustumFrameId = pRend->GetFrameID();
a++;
}
else
{
b++;
}
float fDistance0 = arrFrusrumPlanes[0].DistFromPlane(vSphereCenter);
float fDistance1 = arrFrusrumPlanes[1].DistFromPlane(vSphereCenter);
float fDistance2 = arrFrusrumPlanes[2].DistFromPlane(vSphereCenter);
float fDistance3 = arrFrusrumPlanes[3].DistFromPlane(vSphereCenter);
bool bRes = fDistance0>-fSphereRadius && fDistance1>-fSphereRadius && fDistance2>-fSphereRadius && fDistance3>-fSphereRadius;
/*
#ifdef _DEBUG
{
InitFrustum(fFrustumScale, pRend);
float fDistance0 = arrFrusrumPlanes[0].DistFromPlane(vSphereCenter);
float fDistance1 = arrFrusrumPlanes[1].DistFromPlane(vSphereCenter);
float fDistance2 = arrFrusrumPlanes[2].DistFromPlane(vSphereCenter);
float fDistance3 = arrFrusrumPlanes[3].DistFromPlane(vSphereCenter);
bool bResTest = fDistance0>-fSphereRadius && fDistance1>-fSphereRadius && fDistance2>-fSphereRadius && fDistance3>-fSphereRadius;
assert(bResTest == bRes);
}
#endif
*/
return bRes;
}
};
struct ShadowMapLightSource
{
ShadowMapLightSource(){ ZeroStruct(*this); nDLightId = -1; }
Vec3 vSrcPos; // relative world space
Vec3 vObjSpaceSrcPos; // objects space
float fRadius;
list2<ShadowMapFrustum> m_LightFrustums;
int nDLightId;
int SizeOf();
ShadowMapFrustum * GetShadowMapFrustum(int nId=0)
{
if(nId<m_LightFrustums.Count())
return &m_LightFrustums[nId];
return 0;
}
};
struct ShadowMapLightSourceInstance
{
ShadowMapLightSourceInstance() { ZeroStruct(*this); }
ShadowMapLightSource * m_pLS;
Vec3 m_vProjTranslation;
float m_fProjScale;
float m_fDistance;
struct IEntityRender * m_pReceiver;
bool m_bNoDepthTest;
};
#endif

View File

@@ -0,0 +1,184 @@
#if !defined(LINUX)
#include "RenderPCH.h"
#include "SimpleFrameProfiler.h"
CRecursiveFrameProfiler* CRecursiveFrameProfiler::g_arrStack[CRecursiveFrameProfiler::nStackDepth];
int CRecursiveFrameProfiler::g_nStackTop = 0;
CProfilerTimer g_ProfilerTimer;
CSimpleFrameProfilerInfo *CSimpleFrameProfilerInfo::g_arrProfiles[64];
CSimpleFrameProfilerInfo::CSimpleFrameProfilerInfo (const char* szName):
m_szName (szName),
m_nTickTimer (0)
{
m_nIndex = g_nCount * 2;
assert(g_nCount < 64);
g_arrProfiles[g_nCount] = this;
m_bExpanded = false;
m_bExpandable = false;
m_bActive = false;
m_pParent = NULL;
m_nLevel = 0;
++g_nCount;
}
int CSimpleFrameProfilerInfo::g_nCount = 0;
// this is called when the monitored interval starts
void CSimpleFrameProfilerInfo::startInterval()
{
flush();
m_nTickTimer -= g_ProfilerTimer.getTicks();
++m_nCounter;
}
void CSimpleFrameProfilerInfo::flush()
{
int nCurrentFrame = gRenDev->GetFrameID();
if (nCurrentFrame != m_nFrame)
{
// clean up statistics if the frames didn't go in sequence,
// or add to statistics if they did
if (nCurrentFrame - m_nFrame > 16)
{
m_HistTime.clear();
m_HistCount.clear();
}
else
{
m_HistTime.add(g_ProfilerTimer.ticksToMilliseconds(m_nTickTimer));
m_HistCount.add((float)m_nCounter);
}
m_nTickTimer = 0;
m_nFrame = nCurrentFrame;
m_nCounter = 0;
}
}
void CSimpleFrameProfilerInfo::endInterval()
{
m_nTickTimer += g_ProfilerTimer.getTicks();
}
void CSimpleFrameProfilerInfo::startDelay()
{
m_nTickTimer += g_ProfilerTimer.getTicks();
}
void CSimpleFrameProfilerInfo::endDelay()
{
m_nTickTimer -= g_ProfilerTimer.getTicks();
}
void CSimpleFrameProfilerInfo::drawLabel (float fRow, float* fColor, const char* szText)
{
gRenDev->Draw2dLabel (1+(float)m_nLevel*24.0f, fRow*13+50, 1.4f, fColor, false, "%s", szText);
}
static float g_fColorHeader[4] = {0.5f,0.9f,1,0.75f};
void CSimpleFrameProfilerInfo::drawHeaderLabel()
{
drawLabel (-1.25f, g_fColorHeader, " max ave now min");
}
void CSimpleFrameProfilerInfo::drawStatistics (float fRow, float* fColor, const char* szLabel, CProfilerTimerHistory<float,64>& rProfiler)
{
// draw the profiler statistics gathered on the previous frame
char szBuf[128];
sprintf (szBuf, "%22s %7.2f%7.2f%7.2f%7.2f",
szLabel,
rProfiler.getMax (),
rProfiler.getAve (),
rProfiler.getLast(),
rProfiler.getMin()
);
drawLabel (fRow, fColor, szBuf);
}
__int64 CProfilerTimer::g_nTicksPerSecond = 1000000000;
double CProfilerTimer::g_fSecondsPerTick = 1e-9;
double CProfilerTimer::g_fMilliSecondsPerTick = 1e-6;
unsigned CProfilerTimer::g_nCPUHerz = 1000000000;
void CProfilerTimer::init() // called once
{
#ifdef WIN32
QueryPerformanceFrequency ((LARGE_INTEGER*)&g_nTicksPerSecond);
#endif //WIN32
#ifdef GAMECUBE
g_nTicksPerSecond = OS_CORE_CLOCK; //its a simple define on GC: 486.000.000
g_nCPUHerz = OS_CORE_CLOCK;
#endif
g_fSecondsPerTick = 1.0 / (double)g_nTicksPerSecond;
g_fMilliSecondsPerTick = 1000.0 / (double)g_nTicksPerSecond;
#ifdef WIN32
HKEY hKey;
DWORD dwSize = sizeof(g_nCPUHerz);
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey)
&&ERROR_SUCCESS == RegQueryValueEx (hKey, "~MHz", NULL, NULL, (LPBYTE)&g_nCPUHerz, &dwSize))
{
g_nCPUHerz *= 1000000;
g_fSecondsPerTick = 1.0/(double)g_nCPUHerz;
g_fMilliSecondsPerTick = 1000.0/(double)g_nCPUHerz;
}
else
g_nCPUHerz = 1000000000;
#endif //WIN32
#ifdef _XBOX
//@FIXME: Hack for XBOX
g_nCPUHerz = 800*1000*1000; // 800 Mhz
g_fSecondsPerTick = 1.0/(double)g_nCPUHerz;
g_fMilliSecondsPerTick = 1000.0/(double)g_nCPUHerz;
#endif //XBOX
}
void CProfilerTimer::getTicks(__int64* pnTime)
{
#ifdef WIN64
*pnTime = __rdtsc();
#elif defined(_CPU_X86)
__asm {
mov ebx, pnTime
rdtsc
mov [ebx], eax
mov [ebx+4], edx
}
#else
//#error Please provide a precise value or zero for pnTime
#ifdef GAMECUBE
//I know it looks strange, but this are the cycles!
pnTime = (s64*)(OSGetTime()*12);
#elif defined(WIN64)
*pnTime = __rdtsc();
#endif
#endif
}
float CProfilerTimer::ticksToSeconds (__int64 nTime)
{
return float(g_fSecondsPerTick * nTime);
}
float CProfilerTimer::ticksToMilliseconds (__int64 nTime)
{
return float(g_fMilliSecondsPerTick * nTime);
}
#endif // !defined(LINUX)

View File

@@ -0,0 +1,19 @@
//////////////////////////////////////////////////////////////////////////
// A simple profiler useful for collecting multiple call times per frame
// and displaying their different average statistics.
// For usage, see the bottom of the file
//////////////////////////////////////////////////////////////////////////
#ifndef _SIMPLE_FRAME_PROFILER_
#define _SIMPLE_FRAME_PROFILER_
// set #if 0 here if you don't want profiling to be compiled in the code
#if ENABLE_FRAME_PROFILER
#define PROFILE_FRAME(id) FRAME_PROFILER_FAST( "Renderer:" #id,iSystem,PROFILE_RENDERER,g_bProfilerEnabled )
#else
#define PROFILE_FRAME(id)
#endif
#endif

View File

@@ -0,0 +1,615 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek SuperFramework Source code
//
// (c) by Crytek GmbH 2003. All rights reserved.
// Used with permission to distribute for non-commercial purposes.
//
//
// File:TangentSpaceCalculation.h
// Description: calculated the tangent space base vector for a given mesh
// Dependencies: none
// Documentation: "How to calculate tangent base vectors.doc"
//
// Usage:
// implement the proxy class: CTriangleInputProxy
// instance the proxy class: CTriangleInputProxy MyProxy(MyData);
// instance the calculation helper: CTangentSpaceCalculation<MyProxy> MyTangent;
// do the calculation: MyTangent.CalculateTangentSpace(MyProxy);
// get the data back: MyTangent.GetTriangleIndices(), MyTangent.GetBase()
//
// History:
// - 12/07/2002: Created by Martin Mittring as part of CryEngine
// - 08/18/2003: MM improved stability (no illegal floats) with bad input data
// - 08/19/2003: MM added check for input data problems (DebugMesh() is deactivated by default)
// - 10/02/2003: MM removed rundundant code
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <vector> // STL vector<>
#include <map> // STL map<,,> multimap<>
#define BASEMATRIXMERGEBIAS 0.9f
/* // use this as reference
class CTriangleInputProxy
{
public:
//! /return 0..
DWORD GetTriangleCount( void ) const;
//! /param indwTriNo 0..
//! /param outdwPos
//! /param outdwNorm
//! /param outdwUV
void GetTriangleIndices( const DWORD indwTriNo, DWORD outdwPos[3], DWORD outdwNorm[3], DWORD outdwUV[3] ) const;
//! /param indwPos 0..
//! /param outfPos
void GetPos( const DWORD indwPos, float outfPos[3] ) const;
//! /param indwPos 0..
//! /param outfUV
void GetUV( const DWORD indwPos, float outfUV[2] ) const;
};
*/
// ---------------------------------------------------------------------------------------------------------------
// InputProxy - use CTriangleInputProxy as reference
template <class InputProxy>
class CTangentSpaceCalculation
{
public:
// IN ------------------------------------------------
//! /param inInput - the normals are only used as smoothing input - we calculate the normals ourself
void CalculateTangentSpace( const InputProxy &inInput );
// OUT -----------------------------------------------
//! /return the number of base vectors that are stored 0..
size_t GetBaseCount( void );
//!
//! /param indwTriNo 0..
//! /param outdwBase
void GetTriangleBaseIndices( const DWORD indwTriNo, DWORD outdwBase[3] );
//! returns a orthogonal base (perpendicular and normalized)
//! /param indwPos 0..
//! /param outU in object/worldspace
//! /param outV in object/worldspace
//! /param outN in object/worldspace
void GetBase( const DWORD indwPos, float *outU, float *outV, float *outN );
private: // -----------------------------------------------------------------
class CVec2
{
public:
float x,y;
CVec2(){}
CVec2(float fXval, float fYval) { x=fXval; y=fYval; }
friend CVec2 operator - (const CVec2 &vec1, const CVec2 &vec2) { return CVec2(vec1.x-vec2.x, vec1.y-vec2.y); }
operator float * () { return((float *)this); }
};
class CVec3
{
public:
float x,y,z;
CVec3(){}
CVec3(float fXval, float fYval, float fZval) { x=fXval; y=fYval; z=fZval; }
friend CVec3 operator - (const CVec3 &vec1, const CVec3 &vec2) { return CVec3(vec1.x-vec2.x, vec1.y-vec2.y, vec1.z-vec2.z); }
friend CVec3 operator - (const CVec3 &vec1) { return CVec3(-vec1.x, -vec1.y, -vec1.z); }
friend CVec3 operator + (const CVec3 &vec1, const CVec3 &vec2) { return CVec3(vec1.x+vec2.x, vec1.y+vec2.y, vec1.z+vec2.z); }
friend CVec3 operator * (const CVec3 &vec1, const float fVal) { return CVec3(vec1.x*fVal, vec1.y*fVal, vec1.z*fVal); }
friend float operator * (const CVec3 &vec1, const CVec3 &vec2) { return( vec1.x*vec2.x + vec1.y*vec2.y + vec1.z*vec2.z); }
operator float * () { return((float *)this); }
void Negate() { x=-x;y=-y;z=-z; }
friend CVec3 normalize( const CVec3 &vec ) { CVec3 ret; float fLen=length(vec); if(fLen<0.00001f)return(vec); fLen=1.0f/fLen;ret.x=vec.x*fLen;ret.y=vec.y*fLen;ret.z=vec.z*fLen;return(ret); }
friend CVec3 cross( const CVec3 &vec1, const CVec3 &vec2 ) { return CVec3(vec1.y*vec2.z-vec1.z*vec2.y, vec1.z*vec2.x-vec1.x*vec2.z, vec1.x*vec2.y-vec1.y*vec2.x); }
friend float length( const CVec3 &invA ) { return (float)sqrt(invA.x*invA.x+invA.y*invA.y+invA.z*invA.z); }
friend float CalcAngleBetween( const CVec3 &invA, const CVec3 &invB )
{
float LengthQ=length(invA)*length(invB);
if(LengthQ<0.0001f)LengthQ=0.0001f; // to prevent division by zero
float f=(invA*invB)/LengthQ;
if(f>1.0f)f=1.0f; // acos need input in the range [-1..1]
else if(f<-1.0f)f=-1.0f; //
float fRet=(float)acos(f); // cosf is not avaiable on every plattform
return(fRet);
}
friend bool IsZero( const CVec3 &invA ) { return(invA.x==0.0f && invA.y==0.0f && invA.z==0.0f); }
friend bool IsNormalized( const CVec3 &invA ) { float f=length(invA);return(f>=0.95f && f<=1.05f); }
};
class CBaseIndex
{
public:
DWORD m_dwPosNo; //!< 0..
DWORD m_dwNormNo; //!< 0..
};
// helper to get order for CVertexLoadHelper
struct CBaseIndexOrder: public std::binary_function< CBaseIndex, CBaseIndex, bool>
{
bool operator() ( const CBaseIndex &a, const CBaseIndex &b ) const
{
// first sort by position
if(a.m_dwPosNo<b.m_dwPosNo)return(true);
if(a.m_dwPosNo>b.m_dwPosNo)return(false);
// then by normal
if(a.m_dwNormNo<b.m_dwNormNo)return(true);
if(a.m_dwNormNo>b.m_dwNormNo)return(false);
return(false);
}
};
class CBase33
{
public:
CBase33() { }
CBase33(CVec3 Uval, CVec3 Vval, CVec3 Nval) { u=Uval; v=Vval; n=Nval; }
CVec3 u; //!<
CVec3 v; //!<
CVec3 n; //!< is part of the tangent base but can be used also as vertex normal
};
class CTriBaseIndex
{
public:
DWORD p[3]; //!< index in m_BaseVectors
};
// output data -----------------------------------------------------------------------------------
std::vector<CTriBaseIndex> m_TriBaseAssigment; //!< [0..dwTriangleCount]
std::vector<CBase33> m_BaseVectors; //!< [0..] generated output data
//! /param indwPosNo
//! /param indwNormNo
CBase33 &GetBase( std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> &inMap, const DWORD indwPosNo, const DWORD indwNormNo );
private:
//! creates, copies or returns a reference
//! /param inMap
//! /param indwPosNo
//! /param indwNormNo
//! /param inU weighted
//! /param inV weighted
//! /param inN normalized
DWORD AddUV2Base( std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> &inMap, const DWORD indwPosNo, const DWORD indwNormNo, const CVec3 &inU, const CVec3 &inV, const CVec3 &inNormN );
//! /param inMap
//! /param indwPosNo
//! /param indwNormNo
//! /param inNormal weighted normal
void AddNormal2Base( std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> &inMap, const DWORD indwPosNo, const DWORD indwNormNo, const CVec3 &inNormal );
//! this code was heavly tested with external test app by SergiyM and MartinM
//! rotates the input vector with the rotation to-from
//! /param vFrom has to be normalized
//! /param vTo has to be normalized
//! /param vInput
static CVec3 Rotate( const CVec3 &vFrom, const CVec3 &vTo, const CVec3 &vInput )
{
// no mesh is perfect
// assert(IsNormalized(vFrom));
// no mesh is perfect
// assert(IsNormalized(vTo));
CVec3 vRotAxis=cross(vFrom,vTo); // rotation axis
float fSin=length(vRotAxis);
float fCos=vFrom*vTo;
if(fSin<0.00001f) // no rotation
return(vInput);
vRotAxis=vRotAxis*(1.0f/fSin); // normalize
CVec3 vFrom90deg=normalize(cross(vRotAxis,vFrom)); // perpendicular to vRotAxis and vFrom90deg
// Base is vFrom,vFrom90deg,vRotAxis
float fXInPlane=vFrom*vInput;
float fYInPlane=vFrom90deg*vInput;
CVec3 a=vFrom*(fXInPlane*fCos-fYInPlane*fSin);
CVec3 b=vFrom90deg*(fXInPlane*fSin+fYInPlane*fCos);
CVec3 c=vRotAxis*(vRotAxis*vInput);
return( a + b + c );
}
void DebugMesh( const InputProxy &inInput ) const;
};
// ---------------------------------------------------------------------------------------------------------------
template <class InputProxy>
void CTangentSpaceCalculation<InputProxy>::DebugMesh( const InputProxy &inInput ) const
{
DWORD dwTriCount=inInput.GetTriangleCount();
// search for polygons that use the same indices (input data problems)
for(DWORD a=0;a<dwTriCount;a++)
{
DWORD dwAPos[3],dwANorm[3],dwAUV[3];
inInput.GetTriangleIndices(a,dwAPos,dwANorm,dwAUV);
for(DWORD b=a+1;b<dwTriCount;b++)
{
DWORD dwBPos[3],dwBNorm[3],dwBUV[3];
inInput.GetTriangleIndices(b,dwBPos,dwBNorm,dwBUV);
assert(!( dwAPos[0]==dwBPos[0] && dwAPos[1]==dwBPos[1] && dwAPos[2]==dwBPos[2] ));
assert(!( dwAPos[1]==dwBPos[0] && dwAPos[2]==dwBPos[1] && dwAPos[0]==dwBPos[2] ));
assert(!( dwAPos[2]==dwBPos[0] && dwAPos[0]==dwBPos[1] && dwAPos[1]==dwBPos[2] ));
assert(!( dwAPos[1]==dwBPos[0] && dwAPos[0]==dwBPos[1] && dwAPos[2]==dwBPos[2] ));
assert(!( dwAPos[2]==dwBPos[0] && dwAPos[1]==dwBPos[1] && dwAPos[0]==dwBPos[2] ));
assert(!( dwAPos[0]==dwBPos[0] && dwAPos[2]==dwBPos[1] && dwAPos[1]==dwBPos[2] ));
}
}
}
template <class InputProxy>
void CTangentSpaceCalculation<InputProxy>::CalculateTangentSpace( const InputProxy &inInput )
{
DWORD dwTriCount=inInput.GetTriangleCount();
// clear result
m_BaseVectors.clear();
m_TriBaseAssigment.clear();
m_TriBaseAssigment.reserve(dwTriCount);
assert(m_BaseVectors.size()==0);
assert(m_TriBaseAssigment.size()==0);
std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> mBaseMap; // second=index into m_BaseVectors, generated output data
std::vector<CBase33> vTriangleBase; // base vectors per triangle
// DebugMesh(inInput); // only for debugging - slow
// calculate the base vectors per triangle -------------------------------------------
{
for(DWORD i=0;i<dwTriCount;i++)
{
// get data from caller ---------------------------
DWORD dwPos[3],dwNorm[3],dwUV[3];
inInput.GetTriangleIndices(i,dwPos,dwNorm,dwUV);
CVec3 vPos[3];
CVec2 vUV[3];
for(int e=0;e<3;e++)
{
inInput.GetPos(dwPos[e],vPos[e]);
inInput.GetUV(dwUV[e],vUV[e]);
}
// calculate tangent vectors ---------------------------
CVec3 vA=vPos[1]-vPos[0];
CVec3 vB=vPos[2]-vPos[0];
/*
char str[2024];
sprintf(str,"in: vA=(%.3f %.3f %.3f) vB=(%.3f %.3f %.3f)\n",vA.x,vA.y,vA.z,vA.x,vA.y,vA.z);
OutputDebugString(str);
*/
float fDeltaU1=vUV[1].x-vUV[0].x;
float fDeltaU2=vUV[2].x-vUV[0].x;
float fDeltaV1=vUV[1].y-vUV[0].y;
float fDeltaV2=vUV[2].y-vUV[0].y;
float div =(fDeltaU1*fDeltaV2-fDeltaU2*fDeltaV1);
CVec3 vU,vV,vN=normalize(cross(vA,vB));
if(div!=0.0)
{
// area(u1*v2-u2*v1)/2
float fAreaMul2=fabsf(fDeltaU1*fDeltaV2-fDeltaU2*fDeltaV1); // weight the tangent vectors by the UV triangles area size (fix problems with base UV assignment)
float a = fDeltaV2/div;
float b = -fDeltaV1/div;
float c = -fDeltaU2/div;
float d = fDeltaU1/div;
vU=normalize(vA*a+vB*b)*fAreaMul2;
vV=normalize(vA*c+vB*d)*fAreaMul2;
}
else
{
vU=CVec3(1,0,0);vV=CVec3(0,1,0);
}
vTriangleBase.push_back(CBase33(vU,vV,vN));
}
}
// distribute the normals to the vertices
{
// we create a new tangent base for every vertex index that has a different normal (later we split further for mirrored use)
// and sum the base vectors (weighted by angle and mirrored if necessary)
for(DWORD i=0;i<dwTriCount;i++)
{
DWORD e;
// get data from caller ---------------------------
DWORD dwPos[3],dwNorm[3],dwUV[3];
inInput.GetTriangleIndices(i,dwPos,dwNorm,dwUV);
CBase33 TriBase=vTriangleBase[i];
CVec3 vPos[3];
for(e=0;e<3;e++) inInput.GetPos(dwPos[e],vPos[e]);
// for each triangle vertex
for(e=0;e<3;e++)
{
float fWeight=CalcAngleBetween( vPos[(e+2)%3]-vPos[e],vPos[(e+1)%3]-vPos[e] ); // weight by angle to fix the L-Shape problem
// float fWeight=length(cross( vPos[(e+2)%3]-vPos[e],vPos[(e+1)%3]-vPos[e] )); // weight by area, that does not fix the L-Shape problem 100%
if(fWeight<=0.0f)
fWeight=0.0001f;
AddNormal2Base(mBaseMap,dwPos[e],dwNorm[e],TriBase.n*fWeight);
}
}
}
// distribute the uv vectors to the vertices
{
// we create a new tangent base for every vertex index that has a different normal
// if the base vectors does'nt fit we split as well
for(DWORD i=0;i<dwTriCount;i++)
{
DWORD e;
// get data from caller ---------------------------
DWORD dwPos[3],dwNorm[3],dwUV[3];
CTriBaseIndex Indx;
inInput.GetTriangleIndices(i,dwPos,dwNorm,dwUV);
CBase33 TriBase=vTriangleBase[i];
CVec3 vPos[3];
for(e=0;e<3;e++) inInput.GetPos(dwPos[e],vPos[e]);
// for each triangle vertex
for(e=0;e<3;e++)
{
float fWeight=CalcAngleBetween( vPos[(e+2)%3]-vPos[e],vPos[(e+1)%3]-vPos[e] ); // weight by angle to fix the L-Shape problem
// float fWeight=length(cross( vPos[(e+2)%3]-vPos[e],vPos[(e+1)%3]-vPos[e] )); // weight by area, that does not fix the L-Shape problem 100%
Indx.p[e]=AddUV2Base(mBaseMap,dwPos[e],dwNorm[e],TriBase.u*fWeight,TriBase.v*fWeight,normalize(TriBase.n));
}
m_TriBaseAssigment.push_back(Indx);
}
}
// orthogonalize the base vectors per vertex -------------------------------------------
{
typename std::vector<CBase33>::iterator it;
for(it=m_BaseVectors.begin();it!=m_BaseVectors.end();++it)
{
CBase33 &ref=(*it);
// rotate u and v in n plane
{
// (N is dominating, U and V equal weighted)
CVec3 vUout,vVout,vNout;
vNout=normalize(ref.n);
vUout = ref.u - vNout * (vNout*ref.u); // project u in n plane
vVout = ref.v - vNout * (vNout*ref.v); // project v in n plane
ref.u=normalize(vUout);ref.v=normalize(vVout);ref.n=vNout;
//assert(ref.u.x>=-1 && ref.u.x<=1);
//assert(ref.u.y>=-1 && ref.u.y<=1);
//assert(ref.u.z>=-1 && ref.u.z<=1);
//assert(ref.v.x>=-1 && ref.v.x<=1);
//assert(ref.v.y>=-1 && ref.v.y<=1);
//assert(ref.v.z>=-1 && ref.v.z<=1);
//assert(ref.n.x>=-1 && ref.n.x<=1);
//assert(ref.n.y>=-1 && ref.n.y<=1);
//assert(ref.n.z>=-1 && ref.n.z<=1);
}
}
}
}
template <class InputProxy>
DWORD CTangentSpaceCalculation<InputProxy>::AddUV2Base( std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> &inMap,
const DWORD indwPosNo, const DWORD indwNormNo, const CVec3 &inU, const CVec3 &inV, const CVec3 &inNormN )
{
// no mesh is perfect
// assert(IsNormalized(inNormN));
CBaseIndex Indx;
Indx.m_dwPosNo=indwPosNo;
Indx.m_dwNormNo=indwNormNo;
typename std::multimap<CBaseIndex,DWORD,CBaseIndexOrder>::iterator iFind,iFindEnd;
iFind = inMap.lower_bound(Indx);
assert(iFind!=inMap.end());
CVec3 vNormal=m_BaseVectors[(*iFind).second].n;
iFindEnd = inMap.upper_bound(Indx);
DWORD dwBaseUVIndex=0xffffffff; // init with not found
bool bParity=(cross(inU,inV)*inNormN>0.0f);
for(;iFind!=iFindEnd;++iFind)
{
CBase33 &refFound=m_BaseVectors[(*iFind).second];
if(!IsZero(refFound.u))
{
bool bParityRef=(cross(refFound.u,refFound.v)*refFound.n>0.0f);
bool bParityCheck=(bParityRef==bParity);
if(!bParityCheck)continue;
// bool bHalfAngleCheck=normalize(inU+inV) * normalize(refFound.u+refFound.v) > 0.0f;
CVec3 vRotHalf=Rotate(normalize(refFound.n),inNormN,normalize(refFound.u+refFound.v));
bool bHalfAngleCheck=normalize(inU+inV) * vRotHalf > 0.0f;
// // bool bHalfAngleCheck=normalize(normalize(inU)+normalize(inV)) * normalize(normalize(refFound.u)+normalize(refFound.v)) > 0.0f;
if(!bHalfAngleCheck)continue;
}
dwBaseUVIndex=(*iFind).second;break;
}
if(dwBaseUVIndex==0xffffffff) // not found
{
// otherwise create a new base
CBase33 Base( CVec3(0,0,0), CVec3(0,0,0), vNormal );
dwBaseUVIndex = m_BaseVectors.size();
inMap.insert( std::pair<CBaseIndex,DWORD>(Indx,dwBaseUVIndex) );
m_BaseVectors.push_back(Base);
}
CBase33 &refBaseUV=m_BaseVectors[dwBaseUVIndex];
refBaseUV.u=refBaseUV.u+inU;
refBaseUV.v=refBaseUV.v+inV;
//no mesh is perfect
if(inU.x!=0.0f || inU.y!=0.0f || inU.z!=0.0f)
assert(refBaseUV.u.x!=0.0f || refBaseUV.u.y!=0.0f || refBaseUV.u.z!=0.0f);
// no mesh is perfect
if(inV.x!=0.0f || inV.y!=0.0f || inV.z!=0.0f)
assert(refBaseUV.v.x!=0.0f || refBaseUV.v.y!=0.0f || refBaseUV.v.z!=0.0f);
return(dwBaseUVIndex);
}
template <class InputProxy>
void CTangentSpaceCalculation<InputProxy>::AddNormal2Base( std::multimap<CBaseIndex,DWORD,CBaseIndexOrder> &inMap,
const DWORD indwPosNo, const DWORD indwNormNo, const CVec3 &inNormal )
{
CBaseIndex Indx;
Indx.m_dwPosNo=indwPosNo;
Indx.m_dwNormNo=indwNormNo;
typename std::multimap<CBaseIndex,DWORD,CBaseIndexOrder>::iterator iFind = inMap.find(Indx);
DWORD dwBaseNIndex;
if(iFind!=inMap.end()) // found
{
// resuse the existing one
dwBaseNIndex=(*iFind).second;
}
else
{
// otherwise create a new base
CBase33 Base( CVec3(0,0,0), CVec3(0,0,0), CVec3(0,0,0) );
dwBaseNIndex=m_BaseVectors.size();
inMap.insert( std::pair<CBaseIndex,DWORD>(Indx,dwBaseNIndex) );
m_BaseVectors.push_back(Base);
}
CBase33 &refBaseN=m_BaseVectors[dwBaseNIndex];
refBaseN.n=refBaseN.n+inNormal;
}
template <class InputProxy>
void CTangentSpaceCalculation<InputProxy>::GetBase( const DWORD indwPos, float *outU, float *outV, float *outN )
{
CBase33 &base=m_BaseVectors[indwPos];
outU[0]=base.u.x;
outV[0]=base.v.x;
outN[0]=base.n.x;
outU[1]=base.u.y;
outV[1]=base.v.y;
outN[1]=base.n.y;
outU[2]=base.u.z;
outV[2]=base.v.z;
outN[2]=base.n.z;
}
template <class InputProxy>
void CTangentSpaceCalculation<InputProxy>::GetTriangleBaseIndices( const DWORD indwTriNo, DWORD outdwBase[3] )
{
assert(indwTriNo<m_TriBaseAssigment.size());
CTriBaseIndex &indx=m_TriBaseAssigment[indwTriNo];
for(DWORD i=0;i<3;i++) outdwBase[i]=indx.p[i];
}
template <class InputProxy>
size_t CTangentSpaceCalculation<InputProxy>::GetBaseCount( void )
{
return(m_BaseVectors.size());
}

View File

@@ -0,0 +1,258 @@
/*=============================================================================
BmpImage.cpp : BMP image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#include "BmpImage.h"
#include "SHEndian.h"
//===========================================================================
//-----------------------------------------------------------------------------
// Some platforms require strict-alignment, which means that values of
// primitive types must be accessed at memory locations which are multiples
// of the size of those types. For instance, a 'long' can only be accessed
// at a memory location which is a multiple of four. Consequently, the
// following endian-conversion functions first copy the raw data into a
// variable of the proper data type using memcpy() prior to attempting to
// access it as the given type.
//-----------------------------------------------------------------------------
static inline ushort us_endian (const byte* ptr)
{
short n;
memcpy(&n, ptr, sizeof(n));
return convert_endian(n);
}
static inline unsigned long ul_endian (const byte* ptr)
{
long n;
memcpy(&n, ptr, sizeof(n));
return convert_endian(n);
}
static inline long l_endian (const byte* ptr)
{
long n;
memcpy(&n, ptr, sizeof(n));
return convert_endian(n);
}
#define BFTYPE(x) us_endian((x) + 0)
#define BFSIZE(x) ul_endian((x) + 2)
#define BFOFFBITS(x) ul_endian((x) + 10)
#define BISIZE(x) ul_endian((x) + 14)
#define BIWIDTH(x) l_endian ((x) + 18)
#define BIHEIGHT(x) l_endian ((x) + 22)
#define BITCOUNT(x) us_endian((x) + 28)
#define BICOMP(x) ul_endian((x) + 30)
#define IMAGESIZE(x) ul_endian((x) + 34)
#define BICLRUSED(x) ul_endian((x) + 46)
#define BICLRIMP(x) ul_endian((x) + 50)
#define BIPALETTE(x) ((x) + 54)
// Type ID
#define BM "BM" // Windows 3.1x, 95, NT, ...
#define BA "BA" // OS/2 Bitmap Array
#define CI "CI" // OS/2 Color Icon
#define CP "CP" // OS/2 Color Pointer
#define IC "IC" // OS/2 Icon
#define PT "PT" // OS/2 Pointer
// Possible values for the header size
#define WinHSize 0x28
#define OS21xHSize 0x0C
#define OS22xHSize 0xF0
// Possible values for the BPP setting
#define Mono 1 // Monochrome bitmap
#define _16Color 4 // 16 color bitmap
#define _256Color 8 // 256 color bitmap
#define HIGHCOLOR 16 // 16bit (high color) bitmap
#define TRUECOLOR24 24 // 24bit (true color) bitmap
#define TRUECOLOR32 32 // 32bit (true color) bitmap
// Compression Types
#ifndef BI_RGB
#define BI_RGB 0 // none
#define BI_RLE8 1 // RLE 8-bit / pixel
#define BI_RLE4 2 // RLE 4-bit / pixel
#define BI_BITFIELDS 3 // Bitfields
#endif
//===========================================================================
void CImageBmpFile::mfLoadWindowsBitmap (byte* iBuffer, long iSize)
{
mfSet_dimensions (BIWIDTH(iBuffer), BIHEIGHT(iBuffer));
const int bmp_size = m_Width * m_Height;
m_eFormat = eIF_Bmp;
byte *iPtr = iBuffer + BFOFFBITS(iBuffer);
// The last scanline in BMP corresponds to the top line in the image
int buffer_y = m_Width * (m_Height - 1);
bool blip = false;
if (BITCOUNT(iBuffer) == _256Color && BICLRUSED(iBuffer))
{
mfSet_ImageSize(m_Width * m_Height);
byte *buffer = mfGet_image();
m_pPal = new SRGBPixel [256];
SRGBPixel *pwork = m_pPal;
byte *inpal = BIPALETTE(iBuffer);
mfSet_bps(8);
for (int color=0; color<256; color++, pwork++)
{
// Whacky BMP palette is in BGR order.
pwork->blue = *inpal++;
pwork->green = *inpal++;
pwork->red = *inpal++;
pwork->alpha = 255;
inpal++; // Skip unused byte.
}
if (BICOMP(iBuffer) == BI_RGB)
{
// Read the pixels from "top" to "bottom"
while (iPtr < iBuffer + iSize && buffer_y >= 0)
{
memcpy (buffer + buffer_y, iPtr, m_Width);
iPtr += m_Width;
buffer_y -= m_Width;
} /* endwhile */
}
else
if (BICOMP(iBuffer) == BI_RLE8)
{
// Decompress pixel data
byte rl, rl1, i; // runlength
byte clridx, clridx1; // colorindex
int buffer_x = 0;
while (iPtr < iBuffer + iSize && buffer_y >= 0)
{
rl = rl1 = *iPtr++;
clridx = clridx1 = *iPtr++;
if (rl == 0)
if (clridx == 0)
{
// new scanline
if (!blip)
{
// if we didnt already jumped to the new line, do it now
buffer_x = 0;
buffer_y -= m_Width;
}
continue;
}
else
if (clridx == 1)
// end of bitmap
break;
else
if (clridx == 2)
{
// next 2 bytes mean column- and scanline- offset
buffer_x += *iPtr++;
buffer_y -= (m_Width * (*iPtr++));
continue;
}
else
if (clridx > 2)
rl1 = clridx;
for ( i = 0; i < rl1; i++ )
{
if (!rl)
clridx1 = *iPtr++;
buffer [buffer_y + buffer_x] = clridx1;
if (++buffer_x >= m_Width)
{
buffer_x = 0;
buffer_y -= m_Width;
blip = true;
}
else
blip = false;
}
// pad in case rl == 0 and clridx in [3..255]
if (rl == 0 && (clridx & 0x01))
iPtr++;
}
}
return;
}
else
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR24)
{
mfSet_ImageSize(m_Width * m_Height * 4);
mfSet_bps (24);
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
while (iPtr < iBuffer + iSize && buffer_y >= 0)
{
SRGBPixel *d = buffer + buffer_y;
for (int x = m_Width; x; x--)
{
d->blue = *iPtr++;
d->green = *iPtr++;
d->red = *iPtr++;
d->alpha = 255;
d++;
} /* endfor */
buffer_y -= m_Width;
}
return;
}
else
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR32)
{
mfSet_ImageSize(m_Width * m_Height * 4);
mfSet_bps (32);
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
while (iPtr < iBuffer + iSize && buffer_y >= 0)
{
SRGBPixel *d = buffer + buffer_y;
for (int x = m_Width; x; x--)
{
d->blue = *iPtr++;
d->green = *iPtr++;
d->red = *iPtr++;
d->alpha = *iPtr++;
d++;
} /* endfor */
buffer_y -= m_Width;
}
return;
}
mfSet_error (eIFE_BadFormat, "Unknown BMP image format");
return;
}
CImageBmpFile::CImageBmpFile (byte* ptr, long filesize) : CImageFile ()
{
if ((memcmp (ptr, BM, 2) == 0) && BISIZE(ptr) == WinHSize)
mfLoadWindowsBitmap (ptr, filesize);
else
mfSet_error (eIFE_BadFormat, "Not a Windows BMP file");
return;
}
CImageBmpFile::~CImageBmpFile ()
{
}

View File

@@ -0,0 +1,26 @@
#ifndef BMPIMAGE_H
#define BMPIMAGE_H
/**
* An ImageFile subclass for reading BMP files.
*/
class CImageBmpFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
/// Read the BMP file from the buffer.
CImageBmpFile (byte* buf, long size);
void mfLoadWindowsBitmap (byte* ptr, long filesize);
public:
///
virtual ~CImageBmpFile ();
};
#endif

View File

@@ -0,0 +1,186 @@
/*=============================================================================
CImage.cpp : Common Image class implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "PcxImage.h"
#include "DDSImage.h"
#include "BmpImage.h"
#include "TgaImage.h"
#include "JpgImage.h"
#ifdef PS2
#include "XtfImage.h"
#endif
//---------------------------------------------------------------------------
EImFileError CImageFile::m_eError = eIFE_OK;
char CImageFile::m_Error_detail[256];
char CImageFile::m_CurFileName[128];
CImageFile::CImageFile ()
{
m_pByteImage = NULL;
m_pPal = NULL;
m_eError = eIFE_OK;
m_Error_detail[0] = 0;
m_eFormat = eIF_Unknown;
m_NumMips = 0;
m_Flags = 0;
m_ImgSize = 0;
m_Depth = 1;
}
CImageFile::~CImageFile ()
{
SAFE_DELETE_ARRAY(m_pByteImage);
SAFE_DELETE_ARRAY(m_pPal)
}
void CImageFile::mfSet_dimensions (int w, int h)
{
m_Width = w;
m_Height = h;
}
void CImageFile::mfSet_error (EImFileError error, char* detail)
{
CImageFile::m_eError = error;
if (detail)
strcpy (m_Error_detail, detail);
m_Error_detail[0] = 0;
}
void CImageFile::mfWrite_error (char* extra)
{
if (m_eError == eIFE_OK)
return;
char buf[1000];
int idx = 0;
if (extra)
idx += sprintf (buf+idx, "'%s': ", extra);
switch (m_eError)
{
case eIFE_OK:
return;
case eIFE_IOerror:
idx += sprintf (buf+idx, "IO error");
break;
case eIFE_OutOfMemory:
idx += sprintf (buf+idx, "Out of memory");
break;
case eIFE_BadFormat:
idx += sprintf (buf+idx, "Bad format");
break;
}
if (m_Error_detail[0])
sprintf (buf+idx, " (%s)!\n", m_Error_detail);
else
sprintf (buf+idx, "!\n");
iConsole->Exit ("%s", buf);
}
float gFOpenTime;
int nRejectFOpen;
int nAcceptFOpen;
CImageFile* CImageFile::mfLoad_file (char* szFileName)
{
double dTime0 = 0;
ticks(dTime0);
FILE* pRawFile = iSystem->GetIPak()->FOpen (szFileName, "rb");
unticks(dTime0);
gFOpenTime += (float)(dTime0*1000.0*g_SecondsPerCycle);
if (!pRawFile)
{
nRejectFOpen++;
return NULL;
}
nAcceptFOpen++;
strcpy(m_CurFileName, szFileName);
strlwr(m_CurFileName);
CImageFile* pImageFile = mfLoad_file (pRawFile);
if (pImageFile)
{
strcpy(pImageFile->m_FileName, m_CurFileName);
iSystem->GetIPak()->FClose (pRawFile);
}
else
iSystem->GetILog()->LogToFile("\002Warning: Cannot load texture %s, pImageFile format is invalid", szFileName);
return pImageFile;
}
CImageFile* CImageFile::mfLoad_file (FILE* fp)
{
iSystem->GetIPak()->FSeek (fp, 0, SEEK_END);
long size = iSystem->GetIPak()->FTell (fp);
iSystem->GetIPak()->FSeek (fp, 0, SEEK_SET);
CHK (byte* buf = new byte [size+1]);
iSystem->GetIPak()->FRead (buf, 1, size + 1, fp);
CImageFile* file = mfLoad_file (buf, size);
CHK (delete [] buf);
return file;
}
CImageFile* CImageFile::mfLoad_file (byte* buf, long size)
{
CImageFile* file = NULL;
CImageFile::m_eError = eIFE_OK;
// Catch NULL pointers (for example, when ZIP file is corrupt)
assert (buf);
const char *ext = GetExtension(m_CurFileName);
#ifdef PS2
// Try XTF first
if (!strcmp(ext, ".xtf"))
CHK (file = (CImageFile *)new CImageXtfFile (buf, (int)size));
#endif
// Try DDS first
if (!strcmp(ext, ".dds") || !strcmp(ext, ".ddn") || !strcmp(ext, ".ddp") || !strcmp(ext, ".ddt"))
CHK (file = (CImageFile *)new CImageDDSFile (buf, size));
// If failed, try BMP
if (!strcmp(ext, ".bmp"))
CHK (file = (CImageFile *)new CImageBmpFile (buf, size));
// If failed, try PCX
if (!strcmp(ext, ".pcx"))
CHK (file = (CImageFile *)new CImagePcxFile (buf, size));
#if !defined(NULL_RENDERER)
// Try JPG next
if (!strcmp(ext, ".jpg") || !strcmp(ext, ".jpeg"))
CHK (file = (CImageFile *)new CImageJpgFile (buf, size));
#endif
// As a last resort, try TGA
if (!strcmp(ext, ".tga"))
CHK (file = (CImageFile *)new CImageTgaFile (buf, size));
if (file && (CImageFile::mfGet_error () != eIFE_OK))
{
CHK (delete file);
file = NULL;
} /* endif */
return file;
}
//---------------------------------------------------------------------------

View File

@@ -0,0 +1,203 @@
#ifndef CIMAGE_H
#define CIMAGE_H
#include <assert.h>
#define CHK(x) x
#define SH_LITTLE_ENDIAN
// The mask for extracting just R/G/B from an ulong or SRGBPixel
#ifdef SH_BIG_ENDIAN
# define RGB_MASK 0xffffff00
#else
# define RGB_MASK 0x00ffffff
#endif
/**
* An RGB pixel.
*/
struct SRGBPixel
{
uchar blue, green, red, alpha;
SRGBPixel () /* : red(0), green(0), blue(0), alpha(255) {} */
{ *(unsigned long *)this = (unsigned long)~RGB_MASK; }
SRGBPixel (int r, int g, int b) : red (r), green (g), blue (b), alpha (255) {}
bool eq (const SRGBPixel& p) const { return ((*(unsigned long *)this) & RGB_MASK) == ((*(unsigned long *)&p) & RGB_MASK); }
/// Get the pixel intensity
int Intensity () { return (red + green + blue) / 3; }
};
/**
* An RGB palette entry with statistics information.
*/
struct SRGBPalEntry
{
uchar red, green, blue;
long count;
};
/**
* Possible errors for CImageFile::mfGet_error.
*/
enum EImFileError { eIFE_OK = 0, eIFE_IOerror, eIFE_OutOfMemory, eIFE_BadFormat };
/**
* Eye sensivity to different color components, from NTSC grayscale equation.
* The coefficients are multiplied by 100 and rounded towards nearest integer,
* to facilitate integer math. The squared coefficients are also multiplied
* by 100 and rounded to nearest integer (thus 173 == 1.73, 242 == 2.42 etc).
*/
/// Red component sensivity
#define R_COEF 173
/// Green component sensivity
#define G_COEF 242
/// Blue component sensivity
#define B_COEF 107
/// Eye sensivity to different color components, squared
/// Red component sensivity, squared
#define R_COEF_SQ 299
/// Green component sensivity, squared
#define G_COEF_SQ 587
/// Blue component sensivity, squared
#define B_COEF_SQ 114
#define FIM_NORMALMAP 1
#define FIM_DSDT 2
/**
* An abstract class implementing an image loader. For every image
* type supported, a subclass should be created for loading that image
* type and ImageFile::load_file should be extended to recognize that
* image format.
*/
class CImageFile
{
friend class CImageDDSFile;
friend class CImageCCTFile;
friend class CImageBmpFile;
friend class CImagePcxFile;
friend class CImageJpgFile;
friend class CTexMan;
private:
/// Width of image.
int m_Width;
/// Height of image.
int m_Height;
/// Depth of image.
int m_Depth;
int m_Bps;
int m_ImgSize;
int m_NumMips;
int m_Flags;
/// The image data.
union
{
SRGBPixel* m_pPixImage;
byte* m_pByteImage;
};
/// Last error code.
static EImFileError m_eError;
/// Last error detail information.
static char m_Error_detail[256];
protected:
EImFormat m_eFormat;
SRGBPixel* m_pPal;
/**
* Constructor is private since this object can only be
* created by load_file.
*/
CImageFile ();
/**
* Before failing, a ImageFile subclass should call set_error to
* set the code and detail.
*/
static void mfSet_error (EImFileError error, char* detail = NULL);
/**
* Set the width and height. This will also allocate the 'image'
* buffer to hold the bitmap.
*/
void mfSet_dimensions (int w, int h);
public:
static char m_CurFileName[128];
char m_FileName[128];
///
virtual ~CImageFile ();
///
int mfGet_width () { return m_Width; }
///
int mfGet_height () { return m_Height; }
///
int mfGet_depth () { return m_Depth; }
///
byte* mfGet_image ()
{
if (!m_pByteImage)
{
if (m_ImgSize)
m_pByteImage = new byte [m_ImgSize];
}
return m_pByteImage;
}
///
SRGBPixel* mfGet_palette () { return m_pPal; }
int mfGet_bps () { return m_Bps; }
void mfSet_bps(int b) { m_Bps = b; }
void mfSet_ImageSize (int Size) {m_ImgSize = Size;}
int mfGet_ImageSize () {return m_ImgSize;}
EImFormat mfGetFormat() { return m_eFormat; }
void mfSet_numMips (int num) { m_NumMips = num; }
int mfGet_numMips (void) { return m_NumMips; }
void mfSet_Flags (int Flags) { m_Flags |= Flags; }
int mfGet_Flags () { return m_Flags; }
///
static EImFileError mfGet_error () { return m_eError; }
///
static char* mfGet_error_detail () { return m_Error_detail ? m_Error_detail : (char *)""; }
/// Write a message describing the error on screen.
static void mfWrite_error (char* extra);
/**
* Load the file given the filename.
* This routine will open the file and call load_file (FILE*).
*/
static CImageFile* mfLoad_file (char* filename);
/**
* Load the file given a file pointer.
* This routine will read from the file pointer and call load_file (UByte*, long).
*/
static CImageFile* mfLoad_file (FILE* fp);
/**
* Load the file from a buffer.
* This routine will try to recognize the image file type and then
* created an appropriate ImageFile subclass.
*/
static CImageFile* mfLoad_file (byte* buf, long size);
};
#include "Quantize.h"
#include "Inv_cmap.h"
#endif

View File

@@ -0,0 +1,339 @@
/*=============================================================================
DDSImage.cpp : DDS image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#include "DDSImage.h"
/* needed for DirectX's DDSURFACEDESC2 structure definition */
#if !defined(_XBOX) && !defined(PS2) && !defined(LINUX)
#include <ddraw.h>
#else
#define FOURCC_DXT1 (MAKEFOURCC('D','X','T','1'))
#define FOURCC_DXT2 (MAKEFOURCC('D','X','T','2'))
#define FOURCC_DXT3 (MAKEFOURCC('D','X','T','3'))
#define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4'))
#define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5'))
#endif
#include "dds.h"
#if defined(LINUX)
#include "ILog.h"
#endif
//===========================================================================
static int sDDSSize(int sx, int sy, EImFormat eF )
{
switch (eF)
{
case eIF_DXT1:
case eIF_DXT3:
case eIF_DXT5:
{
int blockSize = (eF == eIF_DXT1) ? 8 : 16;
return ((sx+3)/4)*((sy+3)/4)*blockSize;
}
break;
case eIF_DDS_LUMINANCE:
return sx * sy;
break;
case eIF_DDS_RGB8:
case eIF_DDS_SIGNED_RGB8:
return sx*sy*3;
break;
case eIF_DDS_RGBA8:
return sx*sy*4;
break;
case eIF_DDS_RGBA4:
return sx*sy*2;
break;
case eIF_DDS_DSDT:
return sx*sy*3;
break;
default:
assert(0);
}
return 0;
}
int CImageDDSFile::mfSizeWithMips(int filesize, int sx, int sy, int nMips)
{
int nSize = 0;
for (int i=0; i<nMips; i++)
{
assert(sx || sy);
if (!sx)
sx = 1;
if (!sy)
sy = 1;
nSize += sDDSSize(sx, sy, m_eFormat);
sx >>= 1;
sy >>= 1;
}
assert((int)(filesize-sizeof(DDS_HEADER)-4) >= nSize);
return nSize;
}
static FILE *sFILELog;
CImageDDSFile::CImageDDSFile (byte* ptr, long filesize) : CImageFile ()
{
int sx, sy;
int numMips;
DWORD dwMagic;
DDS_HEADER *ddsh;
dwMagic = *(DWORD *)ptr;
ptr += sizeof(DWORD);
if (dwMagic != MAKEFOURCC('D','D','S',' '))
{
mfSet_error (eIFE_BadFormat, "Not a DDS file");
return;
}
ddsh = (DDS_HEADER *)ptr;
ptr += sizeof(DDS_HEADER);
if (ddsh->dwSize != sizeof(DDS_HEADER))
{
mfSet_error (eIFE_BadFormat, "Unknown DDS file header");
return;
}
sx = ddsh->dwWidth;
sy = ddsh->dwHeight;
numMips = ddsh->dwMipMapCount;
if (numMips == 0)
numMips = 1;
if (ddsh->ddspf.dwFourCC == FOURCC_DXT1)
m_eFormat = eIF_DXT1;
else
if (ddsh->ddspf.dwFourCC == FOURCC_DXT3)
m_eFormat = eIF_DXT3;
else
if (ddsh->ddspf.dwFourCC == FOURCC_DXT5)
m_eFormat = eIF_DXT5;
else
if (ddsh->ddspf.dwFlags == DDS_RGBA && ddsh->ddspf.dwRGBBitCount == 32 && ddsh->ddspf.dwABitMask == 0xff000000)
m_eFormat = eIF_DDS_RGBA8;
else
if (ddsh->ddspf.dwFlags == DDS_RGBA && ddsh->ddspf.dwRGBBitCount == 16)
m_eFormat = eIF_DDS_RGBA4;
else
if (ddsh->ddspf.dwFlags == DDS_RGB && ddsh->ddspf.dwRGBBitCount == 24)
m_eFormat = eIF_DDS_RGB8;
else
if (ddsh->ddspf.dwFlags == DDS_RGB && ddsh->ddspf.dwRGBBitCount == 32)
m_eFormat = eIF_DDS_RGBA8;
else
if (ddsh->ddspf.dwFlags == DDS_LUMINANCE && ddsh->ddspf.dwRGBBitCount == 8)
m_eFormat = eIF_DDS_LUMINANCE;
else
{
mfSet_error (eIFE_BadFormat, "Unknown DDS image format");
return;
}
mfSet_numMips(numMips);
const char *ext = GetExtension(m_CurFileName);
if ((ddsh->dwReserved1[0] & DDS_RESF1_NORMALMAP) ||
!stricmp(ext, ".ddn") || !stricmp(ext, ".ddp") ||
(strlen(m_CurFileName)>4 && (strstr(m_CurFileName, "_ddn") || strstr(m_CurFileName, "_ddp"))))
mfSet_Flags(FIM_NORMALMAP);
else
if ((ddsh->dwReserved1[0] & DDS_RESF1_DSDT) ||
!stricmp(ext, ".ddt") ||
(strlen(m_CurFileName)>4 && strstr(m_CurFileName, "_ddt")))
{
mfSet_Flags(FIM_DSDT);
m_eFormat = eIF_DDS_DSDT;
}
int nDepth = ddsh->dwDepth;
if (nDepth <= 0)
nDepth = 1;
m_Width = sx;
m_Height = sy;
m_Depth = nDepth;
SAFE_DELETE_ARRAY(m_pByteImage);
int size = filesize - sizeof(DDS_HEADER) - 4;
if (m_eFormat == eIF_DDS_DSDT || m_eFormat == eIF_DDS_RGB8)
{
size = mfSizeWithMips(filesize, sx, sy, numMips);
size = size/3*4*nDepth;
}
mfSet_ImageSize(size);
mfGet_image();
int nOffsSrc = 0;
int nOffsDst = 0;
for (int dpt=0; dpt<nDepth; dpt++)
{
if (m_eFormat == eIF_DXT1 || m_eFormat == eIF_DXT3 || m_eFormat == eIF_DXT5)
{
int size = mfSizeWithMips(filesize, sx, sy, numMips);
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
nOffsSrc += size;
nOffsDst += size;
}
else
if (m_eFormat == eIF_DDS_LUMINANCE)
{
int size = mfSizeWithMips(filesize, sx, sy, numMips);
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
nOffsSrc += size;
nOffsDst += size;
}
else
if (m_eFormat == eIF_DDS_RGBA8 || m_eFormat == eIF_DDS_RGBA4)
{
int size = mfSizeWithMips(filesize, sx, sy, numMips);
cryMemcpy(&m_pByteImage[nOffsDst], &ptr[nOffsSrc], size);
nOffsSrc += size;
nOffsDst += size;
}
else
if (m_eFormat == eIF_DDS_RGB8)
{
int size = mfSizeWithMips(filesize, sx, sy, numMips);
int n = size/3;
int sizeDst = n * 4;
for (int i=0; i<n; i++)
{
m_pByteImage[i*4+nOffsDst+0] = ptr[i*3+nOffsSrc+0];
m_pByteImage[i*4+nOffsDst+1] = ptr[i*3+nOffsSrc+1];
m_pByteImage[i*4+nOffsDst+2] = ptr[i*3+nOffsSrc+2];
m_pByteImage[i*4+nOffsDst+3] = 255;
}
nOffsSrc += size;
nOffsDst += sizeDst;
if (CRenderer::CV_r_logusedtextures == 10 && (m_Flags & FIM_NORMALMAP))
{
if (!sFILELog)
sFILELog = fopen("LogBumpTexturesNoAlpha.txt", "w");
if (sFILELog)
{
fprintf(sFILELog, "%s\n", m_CurFileName);
fflush(sFILELog);
}
}
}
else
if (m_eFormat == eIF_DDS_DSDT)
{
int size = mfSizeWithMips(filesize, sx, sy, numMips);
int n = size/3;
int sizeDst = n * 4;
for (int i=0; i<n; i++)
{
m_pByteImage[i*4+nOffsDst+0] = ptr[i*3+nOffsSrc+2];
m_pByteImage[i*4+nOffsDst+1] = ptr[i*3+nOffsSrc+1];
m_pByteImage[i*4+nOffsDst+2] = ptr[i*3+nOffsSrc+0];
m_pByteImage[i*4+nOffsDst+3] = 255;
}
nOffsSrc += size;
nOffsDst += sizeDst;
}
}
}
CImageDDSFile::~CImageDDSFile ()
{
}
void WriteDDS(byte *dat, int wdt, int hgt, int Size, const char *name, EImFormat eF, int NumMips)
{
DWORD dwMagic;
DDS_HEADER ddsh;
memset(&ddsh, 0, sizeof(ddsh));
FILE *fp = fxopen(name, "wb");
if (!fp)
return;
dwMagic = MAKEFOURCC('D','D','S',' ');
fwrite(&dwMagic, 1, sizeof(DWORD), fp);
ddsh.dwSize = sizeof(DDS_HEADER);
ddsh.dwWidth = wdt;
ddsh.dwHeight = hgt;
ddsh.dwMipMapCount = NumMips;
if (!NumMips)
ddsh.dwMipMapCount = 1;
ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE | DDS_SURFACE_FLAGS_MIPMAP;
size_t len = strlen(name);
if (len > 4)
{
if (!stricmp(&name[len-4], ".ddn"))
ddsh.dwReserved1[0] = DDS_RESF1_NORMALMAP;
else
if (!stricmp(&name[len-4], ".ddt"))
ddsh.dwReserved1[0] = DDS_RESF1_DSDT;
}
switch (eF)
{
case eIF_DXT1:
ddsh.ddspf = DDSPF_DXT1;
break;
case eIF_DXT3:
ddsh.ddspf = DDSPF_DXT3;
break;
case eIF_DXT5:
ddsh.ddspf = DDSPF_DXT5;
break;
case eIF_DDS_RGB8:
case eIF_DDS_SIGNED_RGB8:
case eIF_DDS_DSDT:
ddsh.ddspf = DDSPF_R8G8B8;
break;
case eIF_DDS_RGBA8:
ddsh.ddspf = DDSPF_A8R8G8B8;
break;
default:
assert(0);
return;
}
fwrite(&ddsh, 1, sizeof(ddsh), fp);
byte *data = NULL;
if (eF == eIF_DDS_RGB8 || eF == eIF_DDS_SIGNED_RGB8 || eF == eIF_DDS_DSDT)
{
data = new byte[Size];
int n = Size / 3;
for (int i=0; i<n; i++)
{
data[i*3+0] = dat[i*3+2];
data[i*3+1] = dat[i*3+1];
data[i*3+2] = dat[i*3+0];
}
fwrite(data, 1, Size, fp);
}
else
if (eF == eIF_DDS_RGBA8)
{
data = new byte[Size];
int n = Size / 4;
for (int i=0; i<n; i++)
{
data[i*4+0] = dat[i*4+2];
data[i*4+1] = dat[i*4+1];
data[i*4+2] = dat[i*4+0];
data[i*4+3] = dat[i*4+3];
}
}
else
fwrite(dat, 1, Size, fp);
SAFE_DELETE_ARRAY(data);
fclose (fp);
}

View File

@@ -0,0 +1,27 @@
#ifndef DDSIMAGE_H
#define DDSIMAGE_H
/**
* An ImageFile subclass for reading DDS files.
*/
class CImageDDSFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
public:
/// Read the DDS file from the buffer.
CImageDDSFile (byte* buf, long size);
int mfSizeWithMips(int filesize, int sx, int sy, int numMips);
///
virtual ~CImageDDSFile ();
};
void WriteDDS(byte *dat, int wdt, int hgt, int Size, char *name, EImFormat eF, int NumMips);
#endif

View File

@@ -0,0 +1,210 @@
/*********************************************************************NVMH2****
File: Image_DXTC.h
Copyright (C) 1999, 2000 NVIDIA Corporation
Copyright (C) 2002, Ubi Soft Milan
Tiziano Sardone
Comments:
A class to load and decompress DXT textures to 32-bit raw image data format.
.RAW output files can be loaded into photoshop by specifying the resolution
and 4 color channels of 8-bit, interleaved.
A few approaches to block decompression are in place and a simple code timing
function is called. Output of timing test is saved to a local .txt file.
TiZ: some modification to adapt the code to run under PS2.
******************************************************************************/
#if !defined(AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_)
#define AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifdef WIN32
#include <d3d.h>
#endif
#ifdef PS2
/////////////////////////////////////
// should be in ddraw.h
#ifndef MAKEFOURCC
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
#endif //defined(MAKEFOURCC)
#endif
struct TimingInfo; // defined in Image_DXTC.cpp
#define byte unsigned char
#define BYTE unsigned char
//#ifndef PS2
#define WORD unsigned short
#define DWORD unsigned int
#define LONG unsigned int
#define LPVOID void*
#define VOID void
#define CHAR char
#define LARGE_INTEGER int
//#endif
enum PixFormat
{
PF_ARGB,
PF_DXT1,
PF_DXT2,
PF_DXT3,
PF_DXT4,
PF_DXT5,
PF_UNKNOWN,
};
#define COMPRESSED_S3TC_DXT1 PF_DXT1
typedef struct _DDSCAPS2 {
DWORD dwCaps;
DWORD dwCaps2;
DWORD dwCaps3;
DWORD dwCaps4;
} DDSCAPS2, *LPDDSCAPS2;
typedef struct _DDPIXELFORMAT {
DWORD dwSize;
DWORD dwFlags;
DWORD dwFourCC;
union {
DWORD dwRGBBitCount;
DWORD dwYUVBitCount;
DWORD dwZBufferBitDepth;
DWORD dwAlphaBitDepth;
DWORD dwLuminanceBitCount;
DWORD dwBumpBitCount;
DWORD dwPrivateFormatBitCount;
} ;
union {
DWORD dwRBitMask;
DWORD dwYBitMask;
DWORD dwStencilBitDepth;
DWORD dwLuminanceBitMask;
DWORD dwBumpDuBitMask;
DWORD dwOperations;
} ;
union {
DWORD dwGBitMask;
DWORD dwUBitMask;
DWORD dwZBitMask;
DWORD dwBumpDvBitMask;
struct {
WORD wFlipMSTypes;
WORD wBltMSTypes;
} MultiSampleCaps;
} ;
union {
DWORD dwBBitMask;
DWORD dwVBitMask;
DWORD dwStencilBitMask;
DWORD dwBumpLuminanceBitMask;
} ;
union {
DWORD dwRGBAlphaBitMask;
DWORD dwYUVAlphaBitMask;
DWORD dwLuminanceAlphaBitMask;
DWORD dwRGBZBitMask;
DWORD dwYUVZBitMask;
} ;
} DDPIXELFORMAT, *LPDDPIXELFORMAT;
typedef struct _DDCOLORKEY{
DWORD dwColorSpaceLowValue;
DWORD dwColorSpaceHighValue;
} DDCOLORKEY, *LPDDCOLORKEY;
typedef struct _DDSURFACEDESC2 {
DWORD dwSize;
DWORD dwFlags;
DWORD dwHeight;
DWORD dwWidth;
union
{
LONG lPitch;
DWORD dwLinearSize;
} DUMMYUNIONNAMEN_1;
DWORD dwBackBufferCount;
union
{
DWORD dwMipMapCount;
DWORD dwRefreshRate;
} DUMMYUNIONNAMEN_2;
DWORD dwAlphaBitDepth;
DWORD dwReserved;
LPVOID lpSurface;
DDCOLORKEY ddckCKDestOverlay;
DDCOLORKEY ddckCKDestBlt;
DDCOLORKEY ddckCKSrcOverlay;
DDCOLORKEY ddckCKSrcBlt;
DDPIXELFORMAT ddpfPixelFormat;
DDSCAPS2 ddsCaps;
DWORD dwTextureStage;
} DDSURFACEDESC2, *LPDDSURFACEDESC2;
class Image_DXTC
{
public:
unsigned char * m_pCompBytes; // compressed image bytes
unsigned char * m_pDecompBytes;
int m_nCompSize;
int m_nCompLineSz;
char m_strFormat[256];
PixFormat m_CompFormat;
DDSURFACEDESC2 m_DDSD; // read from dds file
bool m_bMipTexture; // texture has mipmaps?
int m_nWidth; // in pixels of uncompressed image
int m_nHeight;
bool LoadFromFile( char * filename ); // true if success
VOID DecodePixelFormat( CHAR* strPixelFormat, DDPIXELFORMAT* pddpf );
void AllocateDecompBytes();
void Decompress();
void DecompressDXT1();
void DecompressDXT2();
void DecompressDXT3();
void DecompressDXT4();
void DecompressDXT5();
void SaveAsRaw8888(const char *name); // save decompressed bits
void SaveAsRaw888(const char *name); // save decompressed bits
void RunTimingSession(); // run a few methods & time the code
// must use dxt5 texture
void Time_Decomp5_01( int ntimes, TimingInfo * info );
void Time_Decomp5_02( int ntimes, TimingInfo * info );
void Time_Decomp5_03( int ntimes, TimingInfo * info );
void Time_Decomp5_04( int ntimes, TimingInfo * info );
Image_DXTC();
virtual ~Image_DXTC();
};
#endif // !defined(AFX_IMAGE_DXTC_H__4B89D8D0_7857_11D4_9630_00A0C996DE3D__INCLUDED_)

View File

@@ -0,0 +1,24 @@
#ifndef GIFIMAGE_H
#define GIFIMAGE_H
/**
* An ImageFile subclass for reading GIF files.
*/
class CImageGifFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
/// Read the GIF file from the buffer.
CImageGifFile (byte* buf, long size);
public:
///
virtual ~CImageGifFile ();
};
#endif

View File

@@ -0,0 +1,143 @@
/*
Copyright (C) 1998 by Tor Andersson and Jorrit Tyberghein
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* !!! not standard... written by Tor Andersson !!!
* get data from memory buffer instead of from file
* assumes that the entire file is in one large block of memory
*
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
#include "Jpeg6/jinclude.h"
#include "Jpeg6/jpeglib.h"
#include "Jpeg6/jerror.h"
/* Expanded data source object for stdio input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
FILE * infile; /* source stream */
JOCTET * buffer; /* start of buffer */
boolean start_of_file; /* have we gotten any data yet? */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
static void
init_source (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
* This is correct behavior for reading a series of images from one source.
*/
src->start_of_file = TRUE;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
* should never happen :)
*/
static boolean
fill_input_buffer (j_decompress_ptr cinfo)
{
/* no-op */
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*/
static void
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
if (num_bytes > 0) {
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
static void
term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from mem buffer.
* Leaves buffer untouched.
*/
void
my_jpeg_memory_src (j_decompress_ptr cinfo, char * inbfr, int len)
{
my_src_ptr src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
src = (my_src_ptr) cinfo->src;
src->buffer = (JOCTET *) inbfr;
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = my_jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = 0L;
src->pub.bytes_in_buffer = len; /*!!! sets to entire file len */
src->pub.next_input_byte = (JOCTET *)inbfr; /*!!! at start of buffer */
}

View File

@@ -0,0 +1,430 @@
/*=============================================================================
JpgImage.cpp : JPG image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#include "JpgImage.h"
#if !defined(WIN64) && !defined(LINUX)
#if defined(PS2)
#include "jpeglib.h"
#include "PS2GDriver.h"
#else
extern "C" {
#include "ijl.h"
}
#endif
/* ==== Constructor ==== */
CImageJpgFile::~CImageJpgFile () {
/* do nothing */
}
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile ()
{
#ifdef PS2
struct jpeg_decompress_struct cinfo;
u_char *pImage=NULL;
pImage=(u_char *)PS2GDRV_LoadJpegImage(mCurFileName, cinfo);
if(pImage)
{
m_eFormat = eIF_Jpg;
mfSet_bps(32);
mfSet_dimensions (cinfo.image_width,cinfo.image_height);
mfSet_ImageSize(m_Width * m_Height * 4);
SRGBPixel *pixels = mfGet_image ();
u_char *pix=pImage;
for(int j=0; j<cinfo.image_height; j++)
{
for(int i=0; i<cinfo.image_width; i++)
{
pixels[0].red=*pix++;
pixels[0].green=*pix++;
pixels[0].blue=*pix++;
pixels[0].alpha=255;
pixels++;
}
}
delete [] pImage;
}
else
{
mfSet_error (eIFE_BadFormat,"Cannot read JPEG file header");
return;
}
#else
JPEG_CORE_PROPERTIES image;
ZeroStruct( image );
SRGBPixel *pixels;
m_eFormat = eIF_Jpg;
if( ijlInit( &image ) != IJL_OK )
{
mfSet_error (eIFE_BadFormat,"Cannot initialize Intel JPEG library");
return;
}
image.JPGBytes = ptr;
image.JPGSizeBytes = filesize;
if( ijlRead( &image, IJL_JBUFF_READPARAMS ) != IJL_OK )
{
mfSet_error (eIFE_BadFormat,"Cannot read JPEG file header");
return;
}
// Set the JPG color space ... this will always be
// somewhat of an educated guess at best because JPEG
// is "color blind" (i.e., nothing in the bit stream
// tells you what color space the data was encoded from).
// However, in this example we assume that we are
// reading JFIF files which means that 3 channel images
// are in the YCbCr color space and 1 channel images are
// in the Y color space.
switch(image.JPGChannels)
{
case 1:
image.JPGColor = IJL_G;
image.DIBChannels = 3;
image.DIBColor = IJL_RGB;
mfSet_bps(24);
break;
case 3:
image.JPGColor = IJL_YCBCR;
image.DIBChannels = 3;
image.DIBColor = IJL_RGB;
mfSet_bps(24);
break;
case 4:
image.JPGColor = IJL_YCBCRA_FPX;
image.DIBChannels = 4;
image.DIBColor = IJL_RGBA_FPX;
mfSet_bps(32);
break;
default:
// This catches everything else, but no
// color twist will be performed by the IJL.
image.DIBColor = (IJL_COLOR)IJL_OTHER;
image.JPGColor = (IJL_COLOR)IJL_OTHER;
image.DIBChannels = image.JPGChannels;
break;
}
image.DIBWidth = image.JPGWidth;
image.DIBHeight = image.JPGHeight;
image.DIBPadBytes = IJL_DIB_PAD_BYTES(image.DIBWidth,image.DIBChannels);
mfSet_dimensions (image.DIBWidth, image.DIBHeight);
mfSet_ImageSize(m_Width * m_Height * 4);
pixels = (SRGBPixel *)mfGet_image ();
int imageSize = (image.DIBWidth * image.DIBChannels + image.DIBPadBytes) * image.DIBHeight;
byte *imageData = new BYTE[ imageSize ];
if( imageData == NULL )
{
mfSet_error (eIFE_OutOfMemory,"Cannot allocate memory for image");
ijlFree( &image );
return;
}
image.DIBBytes = imageData;
if( ijlRead( &image, IJL_JBUFF_READWHOLEIMAGE ) != IJL_OK )
{
mfSet_error (eIFE_IOerror,"Cannot read image data");
ijlFree( &image );
return;
}
if( ijlFree( &image ) != IJL_OK )
{
mfSet_error (eIFE_IOerror,"Cannot free Intel(R) JPEG library");
return;
}
byte *src = imageData;
int width = image.DIBWidth;
int height = image.DIBHeight;
int pad = IJL_DIB_PAD_BYTES(width,4);
if (image.DIBColor == IJL_RGBA_FPX)
{
int line_width = image.DIBWidth * 4 + pad;
for(int i=0; i<height; i++)
{
src = imageData + line_width*i;
for(int j=0; j<width; j++)
{
pixels->red = src[0];
pixels->green = src[1];
pixels->blue = src[2];
pixels->alpha = src[3];
pixels++;
src += 4;
}
}
}
else
{
SRGBPixel *pix = pixels;
int line_width = image.DIBWidth * 3 + pad;
for(int i=0; i<height; i++)
{
src = imageData + line_width*i;
for(int j=0; j<width; j++)
{
pixels->red = src[0];
pixels->green = src[1];
pixels->blue = src[2];
pixels->alpha = 255;
pixels++;
src += 3;
}
}
}
delete [] imageData;
/* And we're done! */
#endif //PS2
}
#endif // WIN64
#ifdef WIN64
extern "C"
{
#include "Jpeg6/Jpeglib.h"
#include "Jmemsrc.c" // include buffer source input code
}
#include <setjmp.h>
/* ==== Error mgmnt ==== */
static char jpg_err_msg[256];
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr *my_error_ptr;
static void my_error_exit (j_common_ptr cinfo)
{
char errmsg [256];
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->format_message) (cinfo,errmsg);
strcpy (jpg_err_msg,errmsg);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
/* ==== Constructor ==== */
CImageJpgFile::~CImageJpgFile () {
/* do nothing */
}
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile () {
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
int bufp;
int i;
SRGBPixel *pixels;
m_eFormat = eIF_Jpg;
/* ==== Step 1: allocate and initialize JPEG decompression object */
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = my_jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
my_jpeg_destroy_decompress(&cinfo);
mfSet_error (eIFE_BadFormat,jpg_err_msg);
return;
}
/* Now we can initialize the JPEG decompression object. */
my_jpeg_create_decompress(&cinfo);
/* ==== Step 2: specify data source (memory buffer, in this case) */
my_jpeg_memory_src(&cinfo, (char *)ptr, filesize);
/* ==== Step 3: read file parameters with jpeg_read_header() */
(void) my_jpeg_read_header(&cinfo, TRUE);
/* ==== Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* ==== Step 5: Start decompressor */
(void) my_jpeg_start_decompress(&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
mfSet_dimensions (cinfo.output_width, cinfo.output_height);
mfSet_ImageSize(cinfo.output_width * cinfo.output_height * 4);
pixels = (SRGBPixel *)mfGet_image();
bufp = 0;
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
/* ==== Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height) {
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void) my_jpeg_read_scanlines(&cinfo, buffer, 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
/* put_scanline_someplace(buffer[0], row_stride); */
if (cinfo.output_components == 1)
{ /* grey scale */
for (i=0;i<row_stride;i++)
{
pixels[bufp].red = buffer[0][i];
pixels[bufp].green = buffer[0][i];
pixels[bufp].blue = buffer[0][i];
pixels[bufp].alpha = 255;
bufp ++;
}
}
else
if (cinfo.output_components == 3)
{ /* rgb triplets */
for (i = 0; i < (int)cinfo.output_width; i++)
{
pixels[bufp].red = buffer[0][i*3+0];
pixels[bufp].green = buffer[0][i*3+1];
pixels[bufp].blue = buffer[0][i*3+2];
pixels[bufp].alpha = 255;
bufp ++;
}
}
else
{
for (i = 0; i < (int)cinfo.output_width; i++)
{
pixels[bufp].red = buffer[0][i*4+0];
pixels[bufp].green = buffer[0][i*4+1];
pixels[bufp].blue = buffer[0][i*4+2];
pixels[bufp].alpha = 255;
bufp ++;
}
}
}
/* ==== Step 7: Finish decompression */
(void) my_jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the buffer data source.
*/
/* ==== Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
my_jpeg_destroy_decompress(&cinfo);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
}
#endif //WIN64
void WriteJPG(byte *dat, int wdt, int hgt, char *name)
{
#if !defined(PS2) && !defined(WIN64) && !defined(NULL_RENDERER)
JPEG_CORE_PROPERTIES image;
ZeroMemory( &image, sizeof( JPEG_CORE_PROPERTIES ) );
if( ijlInit( &image ) != IJL_OK )
return;
byte *data = new byte [wdt*hgt*3];
for (int i=0; i<wdt*hgt; i++)
{
data[i*3+0] = dat[i*4+0];
data[i*3+1] = dat[i*4+1];
data[i*3+2] = dat[i*4+2];
}
// Setup DIB
image.DIBWidth = wdt;
image.DIBHeight = hgt;
image.DIBBytes = data;
image.DIBPadBytes = 0; //IJL_DIB_PAD_BYTES(image.DIBWidth,3);
// Setup JPEG
image.JPGFile = name;
image.JPGWidth = wdt;
image.JPGHeight = hgt;
image.jquality = 100;
image.DIBColor = IJL_RGB;
if( ijlWrite( &image, IJL_JFILE_WRITEWHOLEIMAGE ) != IJL_OK )
{
delete [] data;
return;
}
if( ijlFree( &image ) != IJL_OK )
{
delete [] data;
return;
}
delete [] data;
#else
OutputDebugString("Not Implemented");
#endif //!defined(PS2) && !defined(WIN64)
}

View File

@@ -0,0 +1,24 @@
#ifndef JPGIMAGE_H
#define JPGIMAGE_H
/**
* An ImageFile subclass for reading JPG files.<p>
* This implementation needs libjpeg to read JFIF files.
*/
class CImageJpgFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
/// Read the JPG file from the buffer.
CImageJpgFile (byte* buf, long size);
public:
///
virtual ~CImageJpgFile ();
};
#endif //JPGIMAGE_H

View File

@@ -0,0 +1,179 @@
/*=============================================================================
JpgImage.cpp : JPG image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#if !defined(LINUX)
#include "stdafx.h"
#include "CImage.h"
#include "JpgImage.h"
extern "C"
{
#include "Jpeg6/Jpeglib.h"
#include "Jmemsrc.c" // include buffer source input code
}
#include <setjmp.h>
/* ==== Error mgmnt ==== */
static char jpg_err_msg[256];
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr *my_error_ptr;
static void my_error_exit (j_common_ptr cinfo)
{
char errmsg [256];
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->format_message) (cinfo,errmsg);
strcpy (jpg_err_msg,errmsg);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
/* ==== Constructor ==== */
CImageJpgFile::~CImageJpgFile () {
/* do nothing */
}
CImageJpgFile::CImageJpgFile (byte* ptr, long filesize) : CImageFile () {
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
int bufp;
int i;
SRGBPixel *pixels;
m_eFormat = eIF_Jpg;
/* ==== Step 1: allocate and initialize JPEG decompression object */
/* We set up the normal JPEG error routines, then override error_exit. */
cinfo.err = my_jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
my_jpeg_destroy_decompress(&cinfo);
mfSet_error (eIFE_BadFormat,jpg_err_msg);
return;
}
/* Now we can initialize the JPEG decompression object. */
my_jpeg_create_decompress(&cinfo);
/* ==== Step 2: specify data source (memory buffer, in this case) */
my_jpeg_memory_src(&cinfo, (char *)ptr, filesize);
/* ==== Step 3: read file parameters with jpeg_read_header() */
(void) my_jpeg_read_header(&cinfo, TRUE);
/* ==== Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* ==== Step 5: Start decompressor */
(void) my_jpeg_start_decompress(&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
mfSet_dimensions (cinfo.output_width, cinfo.output_height);
mfSet_ImageSize(cinfo.output_width * cinfo.output_height * 4);
pixels = (SRGBPixel *)mfGet_image();
bufp = 0;
/* JSAMPLEs per row in output buffer */
row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
/* ==== Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height) {
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void) my_jpeg_read_scanlines(&cinfo, buffer, 1);
/* Assume put_scanline_someplace wants a pointer and sample count. */
/* put_scanline_someplace(buffer[0], row_stride); */
if (cinfo.output_components == 1)
{ /* grey scale */
for (i=0;i<row_stride;i++)
{
pixels[bufp].red = buffer[0][i];
pixels[bufp].green = buffer[0][i];
pixels[bufp].blue = buffer[0][i];
pixels[bufp].alpha = 255;
bufp ++;
}
}
else
if (cinfo.output_components == 3)
{ /* rgb triplets */
for (i = 0; i < (int)cinfo.output_width; i++)
{
pixels[bufp].red = buffer[0][i*3+0];
pixels[bufp].green = buffer[0][i*3+1];
pixels[bufp].blue = buffer[0][i*3+2];
pixels[bufp].alpha = 255;
bufp ++;
}
}
else
{
for (i = 0; i < (int)cinfo.output_width; i++)
{
pixels[bufp].red = buffer[0][i*4+0];
pixels[bufp].green = buffer[0][i*4+1];
pixels[bufp].blue = buffer[0][i*4+2];
pixels[bufp].alpha = 255;
bufp ++;
}
}
}
/* ==== Step 7: Finish decompression */
(void) my_jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the buffer data source.
*/
/* ==== Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
my_jpeg_destroy_decompress(&cinfo);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
}
#endif

View File

@@ -0,0 +1,166 @@
/*=============================================================================
PcxImage.cpp : PCX image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#include "PcxImage.h"
#if defined(LINUX)
#include "ILog.h"
#endif
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
short xmin;
short ymin;
short xmax;
short ymax;
short hres;
short vres;
byte palette[48];
char reserved;
char color_planes;
short bytes_per_line;
short palette_type;
char filler[58];
byte data;
} pcx_header;
CImagePcxFile::~CImagePcxFile ()
{
}
CImagePcxFile::CImagePcxFile (byte* ptr, long filesize) : CImageFile ()
{
pcx_header *pcx;
byte* raw, *p, dat;
int x, y, runLength;
int sx, sy;
//
// parse the PCX file
//
pcx = (pcx_header *)ptr;
raw = &pcx->data;
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8
|| pcx->xmax >= 640
|| pcx->ymax >= 480)
{
mfSet_error (eIFE_BadFormat, "not a PCX file");
return;
}
sx=pcx->xmax+1;
sy=pcx->ymax+1;
m_eFormat = eIF_Pcx;
/* Read in global colormap. */
CHK (m_pPal = new SRGBPixel [256]);
p = (byte *)pcx + filesize - 768;
int i;
for (i=0; i<256; i++)
{
m_pPal[i].red = p[0];
m_pPal[i].green = p[1];
m_pPal[i].blue = p[2];
m_pPal[i].alpha = 255;
p += 3;
}
// Set the dimensions which will also allocate the image data
// buffer.
mfSet_dimensions (sx, sy);
mfSet_ImageSize(m_Width * m_Height);
byte *IndexImage = mfGet_image ();
p = IndexImage;
i = 0;
for (y=0 ; y<=pcx->ymax ; y++, p += pcx->xmax+1)
{
for (x=0 ; x<=pcx->xmax ; )
{
dat = *raw++;
if((dat & 0xC0) == 0xC0)
{
runLength = dat & 0x3F;
dat = *raw++;
}
else
runLength = 1;
while(runLength-- > 0)
{
p[x++] = dat;
}
}
}
}
void WritePCX (char *name, byte *data, byte *pal, int width, int height)
{
int i, j, len;
pcx_header *pcx;
byte *pack;
FILE *fp;
pcx = (pcx_header*)malloc (width*height*2+1000);
pcx->manufacturer = 10; // Some programs complains if this is 0
pcx->version = 5;
pcx->encoding = 1;
pcx->bits_per_pixel = 8;
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = width - 1;
pcx->ymax = height - 1;
pcx->hres = width;
pcx->vres = height;
memset (pcx->palette, 0, sizeof(pcx->palette));
pcx->color_planes = 1;
pcx->bytes_per_line = width;
pcx->palette_type = 2;
memset (pcx->filler, 0, sizeof(pcx->filler));
pack = &(pcx->data);
for (i=0; i<height; i++)
{
for (j=0; j<width; j++)
{
if ((*data & 0xc0) != 0xc0)
*pack++ = *data++;
else
{
*pack++ = 0xc1;
*pack++ = *data++;
}
}
// data += width;
}
*pack++ = 0x0c;
for (i=0; i<768; i++)
*pack++ = *pal++;
len = pack - (byte *)pcx;
fp = fxopen (name, "wb");
if (!fp)
return;
fwrite (pcx, len, 1, fp);
fclose (fp);
free (pcx);
}

View File

@@ -0,0 +1,25 @@
#ifndef PCXIMAGE_H
#define PCXIMAGE_H
/**
* An ImageFile subclass for reading PCX files.
*/
class CImagePcxFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
/// Read the PCX file from the buffer.
CImagePcxFile (byte* buf, long size);
public:
///
virtual ~CImagePcxFile ();
};
#endif

View File

@@ -0,0 +1,737 @@
/*=============================================================================
PcxImage.cpp : PCX image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#define HIST_R_BITS 5
#define HIST_G_BITS 6
#define HIST_B_BITS 5
// Amount to shift left R value to get max (hist_r, hist_g, hist_b)
#define HIST_SHIFT_R 1
#define HIST_SHIFT_G 0
#define HIST_SHIFT_B 1
#define HIST_R_MAX (1 << HIST_R_BITS)
#define HIST_G_MAX (1 << HIST_G_BITS)
#define HIST_B_MAX (1 << HIST_B_BITS)
#ifdef SH_LITTLE_ENDIAN
# define R_BIT 0
# define G_BIT 8
# define B_BIT 16
#else
# define R_BIT 24
# define G_BIT 16
# define B_BIT 8
#endif
// Compute masks for effectively separating R,G and B components from a unsigned long.
// For a little-endian machine they are respectively
// 0x000000f8, 0x0000fc00 and 0x00f80000
// For a big-endian machine they are respectively
// 0xf8000000, 0x00fc0000 and 0x0000f800
#define R_MASK ((HIST_R_MAX - 1) << (R_BIT + 8 - HIST_R_BITS))
#define G_MASK ((HIST_G_MAX - 1) << (G_BIT + 8 - HIST_G_BITS))
#define B_MASK ((HIST_B_MAX - 1) << (B_BIT + 8 - HIST_B_BITS))
// The following macro extract the respective color components from a unsigned long
// and transform them into a index in the histogram.
#define INDEX_R(l) ((l & R_MASK) >> (R_BIT + 8 - HIST_R_BITS))
#define INDEX_G(l) ((l & G_MASK) >> (G_BIT + 8 - HIST_G_BITS - HIST_R_BITS))
#define INDEX_B(l) ((l & B_MASK) >> (B_BIT + 8 - HIST_B_BITS - HIST_G_BITS - HIST_R_BITS))
// Calculate index into histogram for given R,G,B components
#define INDEX(r,g,b) (r + (g << HIST_R_BITS) + (b << (HIST_R_BITS + HIST_G_BITS)))
// The storage for color usage histogram
static ushort *hist = NULL;
// Total number of colors that were used to create the histogram
static unsigned hist_pixels;
/*
* A box in color space.
* Both minimal and maximal component bounds are inclusive, that is, the bounds
* Rm = 0, Rx = 255 means the box covers the entire R component range.
* <p>
* This structure is meant to be highly fast, thus only atomic operations
* are implemented for it. After some operations the box may be left in a
* invalid state, thus take care.
*/
struct shColorBox
{
// The minimal and maximal R
byte Rm,Rx;
// The minimal and maximal G
byte Gm,Gx;
// The minimal and maximal B
byte Bm,Bx;
// Color box volume
unsigned Volume;
// Number of pixels in this box
unsigned PixelCount;
// Number of non-zero different color values in this box
unsigned ColorCount;
// Useful function
static inline unsigned Sqr (int x)
{ return x * x; }
// Set box to given bounds
void Set (byte rm, byte rx, byte gm, byte gx, byte bm, byte bx)
{ Rm = rm; Rx = rx; Gm = gm; Gx = gx; Bm = bm; Bx = bx; }
// Compute the volume of box
void ComputeVolume ()
{
// We compute the length of the diagonal of the box rather than the
// proper volume. This also has the side effect that a long narrow
// box looks more "voluminous" thus its more probably that it will
// be split rather than a relatively cubic one.
Volume = Sqr (Rx - Rm) * (R_COEF_SQ << HIST_SHIFT_R) +
Sqr (Gx - Gm) * (G_COEF_SQ << HIST_SHIFT_G) +
Sqr (Bx - Bm) * (B_COEF_SQ << HIST_SHIFT_B);
}
// Count number of non-zero colors within this box
void CountPixels ()
{
PixelCount = ColorCount = 0;
for (int b = Bm; b <= Bx; b++)
for (int g = Gm; g <= Gx; g++)
{
ushort *hp = &hist [INDEX (Rm, g, b)];
for (int r = Rx - Rm; r >= 0; r--, hp++)
if (*hp)
{
PixelCount += *hp;
ColorCount++;
} /* endif */
} /* endfor */
}
// Move Rm up until we find pixels that contain this value
bool ShrinkRm ()
{
byte iRm = Rm;
for (; Rm <= Rx; Rm++)
for (byte b = Bm; b <= Bx; b++)
{
ushort *hp = &hist [INDEX (Rm, Gm, b)];
for (int g = Gx - Gm; g >= 0; g--, hp += HIST_R_MAX)
if (*hp) return (Rm != iRm);
}
return (Rm != iRm);
}
// Move Rx down until we find pixels that contain this value
bool ShrinkRx ()
{
byte iRx = Rx;
for (; Rx >= Rm; Rx--)
for (byte b = Bm; b <= Bx; b++)
{
ushort *hp = &hist [INDEX (Rx, Gm, b)];
for (int g = Gx - Gm; g >= 0; g--, hp += HIST_R_MAX)
if (*hp) return (Rx != iRx);
}
return (Rx != iRx);
}
// Move Gm up until we find pixels that contain this value
bool ShrinkGm ()
{
byte iGm = Gm;
for (; Gm <= Gx; Gm++)
for (byte b = Bm; b <= Bx; b++)
{
ushort *hp = &hist [INDEX (Rm, Gm, b)];
for (int r = Rx - Rm; r >= 0; r--, hp++)
if (*hp) return (Gm != iGm);
}
return (Gm != iGm);
}
// Move Gx down until we find pixels that contain this value
bool ShrinkGx ()
{
byte iGx = Gx;
for (; Gx >= Gm; Gx--)
for (byte b = Bm; b <= Bx; b++)
{
ushort *hp = &hist [INDEX (Rm, Gx, b)];
for (int r = Rx - Rm; r >= 0; r--, hp++)
if (*hp) return (Gx != iGx);
}
return (Gx != iGx);
}
// Move Bm up until we find pixels that contain this value
bool ShrinkBm ()
{
byte iBm = Bm;
for (; Bm <= Bx; Bm++)
for (byte g = Gm; g <= Gx; g++)
{
ushort *hp = &hist [INDEX (Rm, g, Bm)];
for (int r = Rx - Rm; r >= 0; r--, hp++)
if (*hp) return (Bm != iBm);
}
return (Bm != iBm);
}
// Move Bx down until we find pixels that contain this value
bool ShrinkBx ()
{
byte iBx = Bx;
for (; Bx >= Bm; Bx--)
for (byte g = Gm; g <= Gx; g++)
{
ushort *hp = &hist [INDEX (Rm, g, Bx)];
for (int r = Rx - Rm; r >= 0; r--, hp++)
if (*hp) return (Bx != iBx);
}
return (Bx != iBx);
}
// Shrink box: move min/max bounds until we hit an existing color
void Shrink ()
{
ShrinkRm (); ShrinkRx ();
ShrinkGm (); ShrinkGx ();
ShrinkBm (); ShrinkBx ();
}
/**
* Compute the mean color for this box.
* The computation is performed by taking into account each color's
* weight, i.e. number of pixels with this color. Thus resulting palette
* is biased towards most often used colors.
*/
void GetMeanColor (SRGBPixel &color)
{
unsigned rs = 0, gs = 0, bs = 0;
unsigned count = 0;
for (int b = Bm; b <= Bx; b++)
for (int g = Gm; g <= Gx; g++)
{
ushort *hp = &hist [INDEX (Rm, g, b)];
for (int r = Rm; r <= Rx; r++, hp++)
if (*hp)
{
unsigned pixc = *hp;
count += pixc;
rs += pixc * r;
gs += pixc * g;
bs += pixc * b;
} /* endif */
} /* endfor */
// In some extreme cases (textures with zero pixels or
// single-color textures with 1 transparent color)
// we can end here with count == 0; avoid division by zero
if (!count)
{
color = SRGBPixel (0, 0, 0);
return;
}
color.red = ((rs + count / 2) << (8 - HIST_R_BITS)) / count;
color.green = ((gs + count / 2) << (8 - HIST_G_BITS)) / count;
color.blue = ((bs + count / 2) << (8 - HIST_B_BITS)) / count;
}
void FillInverseCMap (byte *icmap, byte index)
{
int Rcount = Rx - Rm + 1;
for (int b = Bm; b <= Bx; b++)
for (int g = Gm; g <= Gx; g++)
memset (&icmap [INDEX (Rm, g, b)], index, Rcount);
}
};
// The storage for color space boxes
static shColorBox *box = NULL;
// Number of valid color boxes
static int boxcount;
// The storage for color indices
static byte *color_index = NULL;
static int __cdecl compare_boxes (const void *i1, const void *i2)
{
int count1 = box [*(byte *)i1].PixelCount;
int count2 = box [*(byte *)i2].PixelCount;
return (count1 > count2) ? -1 : (count1 == count2) ? 0 : +1;
}
//------------------------------------------------------------- The API ------//
// The state of quantization variables
static enum
{
// Uninitialized: initial state
qsNone,
// Counting color frequencies
qsCount,
// Remapping input images to output
qsRemap
} qState = qsNone;
void shQuantizeBegin ()
{
// Clean up, if previous quantization sequence was not finished
shQuantizeEnd ();
// First, allocate the histogram
hist = new ushort [HIST_R_MAX * HIST_G_MAX * HIST_B_MAX];
memset (hist, 0, HIST_R_MAX * HIST_G_MAX * HIST_B_MAX * sizeof (ushort));
hist_pixels = 0;
qState = qsCount;
}
void shQuantizeEnd ()
{
delete [] color_index; color_index = NULL;
delete [] box; box = NULL;
delete [] hist; hist = NULL;
}
void shQuantizeCount (SRGBPixel *image, int pixels, SRGBPixel *transp)
{
// Sanity check
if (!pixels || qState != qsCount)
return;
hist_pixels += pixels;
// Now, count all colors in image
unsigned long *src = (unsigned long *)image;
if (transp)
{
unsigned long tc = (*(unsigned long *)transp) & RGB_MASK;
while (pixels--)
{
unsigned long pix = *src++;
if (tc != (pix & RGB_MASK))
{
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
// do not permit overflow here; stick to MAX_ushort
if (!++pa) --pa;
}
}
}
else
while (pixels--)
{
unsigned long pix = *src++;
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
// do not permit overflow here; stick to MAX_ushort
if (!++pa) --pa;
}
}
void shQuantizeBias (SRGBPixel *colors, int count, int weight)
{
// Sanity check
if (!count || qState != qsCount)
return;
unsigned delta;
if (hist_pixels < (0xffffffff / 100))
delta = ((hist_pixels + 1) * weight / (100 * count));
else
delta = ((hist_pixels / count + 1) * weight) / 100;
if (delta > 0xffff)
delta = 0xffff;
else if (!delta)
return;
// Now, count all colors in image
unsigned long *src = (unsigned long *)colors;
while (count--)
{
unsigned long pix = *src++;
ushort &pa = hist [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
// do not permit overflow here; stick to MAX_ushort
if (unsigned (pa) + delta > 0xffff) pa = 0xffff; else pa += delta;
}
}
void shQuantizePalette (SRGBPixel *&outpalette, int &maxcolors, SRGBPixel *transp)
{
// Sanity check
if (qState != qsCount || !maxcolors)
return;
// Good. Now we create the array of color space boxes.
box = new shColorBox [maxcolors];
box [0].Set (0, HIST_R_MAX - 1, 0, HIST_G_MAX - 1, 0, HIST_B_MAX - 1);
box [0].Shrink ();
box [0].ComputeVolume ();
box [0].CountPixels ();
boxcount = 1;
if (transp)
maxcolors--;
// Loop until we have enough boxes (or we're out of pixels)
while (boxcount < maxcolors)
{
// Find the box that should be split
// We're making this decision the following way:
// - first half of palette we prefer to split boxes that are
// most populated with different colors.
// - the rest of palette we prefer to split largest boxes.
int bi, bestbox = -1;
unsigned bestrating = 0;
if (boxcount < maxcolors / 2)
{
for (bi = 0; bi < boxcount; bi++)
if (bestrating < box [bi].ColorCount)
{
bestrating = box [bi].ColorCount;
bestbox = bi;
}
}
else
{
for (bi = 0; bi < boxcount; bi++)
if (bestrating < box [bi].Volume)
{
bestrating = box [bi].Volume;
bestbox = bi;
}
}
// Out of splittable boxes?
if (bestrating <= 1)
break;
shColorBox &srcbox = box [bestbox];
shColorBox &dstbox = box [boxcount++];
dstbox = srcbox;
// Decide along which of R/G/B axis to split the box
int rlen = (dstbox.Rx - dstbox.Rm) * (R_COEF << HIST_SHIFT_R);
int glen = (dstbox.Gx - dstbox.Gm) * (G_COEF << HIST_SHIFT_G);
int blen = (dstbox.Bx - dstbox.Bm) * (B_COEF << HIST_SHIFT_B);
enum { axisR, axisG, axisB } axis =
(glen < rlen) ?
((rlen < blen) ? axisB : axisR) :
((glen < blen) ? axisB : axisG);
//
// We split each box into two by the plane that goes through given color
// component (one of R,G,B as choosen above). Any of resulting split boxes
// possibly can become smaller if we move one of the five its faces (the
// sixth face sure can't move because it was checked before - the one that
// is opposed to the just-created new face, in the place of split).
// Here goes some ASCII art:
//
// C G K The initial color box ABCD-IJKL was split by a
// *-------*-------* plane and two boxes ABCD-EFGH and EFGH-IJKL
// /| /| /| were created. The boxes cannot be shrinked
// B/ | F/ | J/ | by moving faces ABCD and IJKL (because the
// *-------*-------* | boxes were previously adjusted and any surface
// | *----|--*----|--* passes through at least one used color).
// | /D | /H | /L Now we also see that if the left box
// |/ |/ |/ can be shrinked by moving face, say, ABFE
// *-------*-------* towards DCGH, it is impossible for the right
// A E I box to be shrinked by moving EFJI towards HGKL,
// because the previous whole face ABJI is known
// to pass through at least one used color (and if it is not in the ABFE
// are, then it is surely in the EFJI area). We can say the same about
// the DCGH/HGKL, BCGF/FGKJ and ADHE/EHLI pairs.
//
switch (axis)
{
case axisR:
srcbox.Rx = (srcbox.Rm + srcbox.Rx) / 2;
dstbox.Rm = srcbox.Rx + 1;
srcbox.ShrinkRx ();
dstbox.ShrinkRm ();
if (!srcbox.ShrinkGm ())
dstbox.ShrinkGm ();
if (!srcbox.ShrinkGx ())
dstbox.ShrinkGx ();
if (!srcbox.ShrinkBm ())
dstbox.ShrinkBm ();
if (!srcbox.ShrinkBx ())
dstbox.ShrinkBx ();
break;
case axisG:
srcbox.Gx = (srcbox.Gm + srcbox.Gx) / 2;
dstbox.Gm = srcbox.Gx + 1;
srcbox.ShrinkGx ();
dstbox.ShrinkGm ();
if (!srcbox.ShrinkRm ())
dstbox.ShrinkRm ();
if (!srcbox.ShrinkRx ())
dstbox.ShrinkRx ();
if (!srcbox.ShrinkBm ())
dstbox.ShrinkBm ();
if (!srcbox.ShrinkBx ())
dstbox.ShrinkBx ();
break;
case axisB:
srcbox.Bx = (srcbox.Bm + srcbox.Bx) / 2;
dstbox.Bm = srcbox.Bx + 1;
srcbox.ShrinkBx ();
dstbox.ShrinkBm ();
if (!srcbox.ShrinkRm ())
dstbox.ShrinkRm ();
if (!srcbox.ShrinkRx ())
dstbox.ShrinkRx ();
if (!srcbox.ShrinkGm ())
dstbox.ShrinkGm ();
if (!srcbox.ShrinkGx ())
dstbox.ShrinkGx ();
break;
} /* endswitch */
dstbox.CountPixels ();
srcbox.PixelCount -= dstbox.PixelCount;
srcbox.ColorCount -= dstbox.ColorCount;
srcbox.ComputeVolume ();
dstbox.ComputeVolume ();
} /* endwhile */
// Either we're out of splittable boxes, or we have palsize boxes.
// Assign successive palette indices to all boxes
int count, delta = transp ? 1 : 0;
color_index = new byte [boxcount + delta];
for (count = 0; count < boxcount; count++)
color_index [count] = count;
// Sort palette indices by usage (a side bonus to quantization)
qsort (color_index, boxcount, sizeof (byte), compare_boxes);
// Allocate the palette, if not already allocated
if (!outpalette)
outpalette = new SRGBPixel [maxcolors + delta];
// Fill the unused colormap entries with zeros
memset (&outpalette [boxcount + delta], 0,
(maxcolors - boxcount) * sizeof (SRGBPixel));
// Now compute the mean color for each box
for (count = 0; count < boxcount; count++)
box [color_index [count]].GetMeanColor (outpalette [count + delta]);
// If we have a transparent color, set colormap entry 0 to it
if (delta)
{
for (count = boxcount; count; count--)
color_index [count] = color_index [count - 1] + 1;
color_index [0] = 0;
outpalette [0] = SRGBPixel (0, 0, 0);
}
maxcolors = boxcount + delta;
}
void shQuantizeRemap (SRGBPixel *image, int pixels,
byte *&outimage, SRGBPixel *transp)
{
// Sanity check
if (qState != qsCount && qState != qsRemap)
return;
int count;
// We will re-use the histogram memory for a inverse colormap. However, we
// will need just a byte per element, so we'll assign the address of
// histogram memory block to a pointer of suitable type, and the second
// half of histogram storage remains unused.
byte *icmap = (byte *)hist;
int delta = transp ? 1 : 0;
if (qState == qsCount)
{
// Now, fill inverse colormap with color indices
for (count = 0; count < boxcount; count++)
box [color_index [count + delta] - delta].FillInverseCMap (icmap, count + delta);
qState = qsRemap;
}
// Allocate the picture and the palette
if (!outimage) outimage = new byte [pixels];
unsigned long *src = (unsigned long *)image;
byte *dst = outimage;
count = pixels;
if (transp)
{
unsigned long tc = (*(unsigned long *)transp) & RGB_MASK;
while (count--)
{
unsigned long pix = *src++;
if (tc == (pix & RGB_MASK))
*dst++ = 0;
else
*dst++ = icmap [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
}
}
else
while (count--)
{
unsigned long pix = *src++;
*dst++ = icmap [INDEX_R (pix) + INDEX_G (pix) + INDEX_B (pix)];
}
}
void shQuantizeRemapDither (SRGBPixel *image, int pixels, int pixperline,
SRGBPixel *palette, int colors, byte *&outimage, SRGBPixel *transp)
{
// Sanity check
if (qState != qsCount && qState != qsRemap)
return;
int count;
// We will re-use the histogram memory for a inverse colormap. However, we
// will need just a byte per element, so we'll assign the address of
// histogram memory block to a pointer of suitable type, and the second
// half of histogram storage remains unused.
byte *icmap = (byte *)hist;
int delta = transp ? 1 : 0;
if (qState == qsCount)
{
// Build an inverse colormap (since during dithering we can get color
// indices that did not existed in the original image)
shInverseColormap (colors - delta, palette + delta,
HIST_R_BITS, HIST_G_BITS, HIST_B_BITS, icmap);
if (transp)
for (int i = 0; i < HIST_R_MAX * HIST_G_MAX * HIST_B_MAX; i++)
icmap [i]++;
qState = qsRemap;
}
// Allocate the picture and the palette
if (!outimage) outimage = new byte [pixels];
SRGBPixel *src = image;
byte *dst = outimage;
count = pixels;
int *fserr = (int *)malloc (2 * 3 * (pixperline + 2) * sizeof (int));
memset (fserr, 0, 3 * (pixperline + 2) * sizeof (int));
// odd/even row
unsigned char odd = 0;
while (count > 0)
{
// The alogorithm implements the widely-known and used Floyd-Steinberg
// error distribution - based dithering. The errors are distributed with
// the following weights to the surrounding pixels:
//
// (here) 7/16
// 3/16 5/16 1/16
//
// Even lines are traversed left to right, odd lines backwards.
SRGBPixel *cursrc;
byte *curdst;
int *curerr, *nexterr;
int dir;
if (odd)
{
cursrc = src + pixperline - 1;
curdst = dst + pixperline - 1;
curerr = fserr + 2 * 3 * (pixperline + 2) - 6;
nexterr = fserr + 3 * (pixperline + 2) - 3;
dir = -1;
}
else
{
cursrc = src;
curdst = dst;
curerr = fserr + 3;
nexterr = fserr + 3 * (pixperline + 2);
dir = 1;
}
int dir3 = dir * 3;
// We will keep the errors for pixels (x+1, y) in the variable "err10",
// the error for the pixel right below us (x, y + 1) in "err01", and
// the error at (x + 1, y + 1) in "err11". The error for the pixel at
// (x - 1, y + 1) will be flushed into the errors array. This way, we
// will have just one memory read and one memory write per pixel.
// Well, in fact we have much more (x86 is terribly lacking registers)
// but anyway they go through the cache.
int err10r = 0, err01r = 0, err11r = 0;
int err10g = 0, err01g = 0, err11g = 0;
int err10b = 0, err01b = 0, err11b = 0;
for (int fspix = pixperline; fspix; fspix--,
cursrc += dir, curdst += dir,
curerr += dir3, nexterr += dir3)
{
SRGBPixel srcpix = *cursrc;
if (transp && transp->eq (srcpix))
{
*curdst = 0;
err10r = err10g = err10b = 0;
nexterr [0] = err01r; nexterr [1] = err01g; nexterr [2] = err01b;
err01r = err11r; err01g = err11g; err01b = err11b;
err11r = err11g = err11b = 0;
continue;
}
int r = srcpix.red + ((err10r + curerr [0]) / 16);
if (r < 0) r = 0; if (r > 255) r = 255;
int g = srcpix.green + ((err10g + curerr [1]) / 16);
if (g < 0) g = 0; if (g > 255) g = 255;
int b = srcpix.blue + ((err10b + curerr [2]) / 16);
if (b < 0) b = 0; if (b > 255) b = 255;
byte pix = icmap [((r >> (8 - HIST_R_BITS)) << (HIST_G_BITS + HIST_B_BITS)) |
((g >> (8 - HIST_G_BITS)) << HIST_B_BITS) |
((b >> (8 - HIST_B_BITS)))];
*curdst = pix;
SRGBPixel realcolor = palette [pix];
err10r = r - realcolor.red;
nexterr [0] = err01r + err10r * 3; // * 3
err01r = err11r + err10r * 5; // * 5
err11r = err10r; // * 1
err10r *= 7; // * 7
err10g = g - realcolor.green;
nexterr [1] = err01g + err10g * 3; // * 3
err01g = err11g + err10g * 5; // * 5
err11g = err10g; // * 1
err10g *= 7; // * 7
err10b = b - realcolor.blue;
nexterr [2] = err01b + err10b * 3; // * 3
err01b = err11b + err10b * 5; // * 5
err11b = err10b; // * 1
err10b *= 7; // * 7
}
// flush cached errors into error array
nexterr [0] = err01r;
nexterr [1] = err01g;
nexterr [2] = err01b;
src += pixperline;
dst += pixperline;
odd ^= 1;
count -= pixperline;
}
free(fserr);
}
void shQuantizeRGB (SRGBPixel *image, int pixels, int pixperline,
byte *&outimage, SRGBPixel *&outpalette, int &maxcolors, bool dither)
{
shQuantizeBegin ();
shQuantizeCount (image, pixels);
shQuantizePalette (outpalette, maxcolors);
if (dither)
shQuantizeRemapDither (image, pixels, pixperline, outpalette, maxcolors, outimage);
else
shQuantizeRemap (image, pixels, outimage);
shQuantizeEnd ();
}

View File

@@ -0,0 +1,28 @@
#ifndef __QUANTIZE_H__
#define __QUANTIZE_H__
extern void shQuantizeRGB (SRGBPixel *image, int pixels, int pixperline,
byte *&outimage, SRGBPixel *&outpalette, int &maxcolors, bool dither);
/// Begin quantization
extern void shQuantizeBegin ();
/// Finish quantization
extern void shQuantizeEnd ();
/// Count the colors in a image and update the color histogram
extern void shQuantizeCount (SRGBPixel *image, int pixels,
SRGBPixel *transp = NULL);
/// Bias the color histogram towards given colors (weight = 0..100)
extern void shQuantizeBias (SRGBPixel *colors, int count, int weight);
/// Compute the optimal palette for all images passed to QuantizeCount()
extern void shQuantizePalette (SRGBPixel *&outpalette, int &maxcolors,
SRGBPixel *transp = NULL);
/// Remap a image to the palette computed by shQuantizePalette()
extern void shQuantizeRemap (SRGBPixel *image, int pixels,
byte *&outimage, SRGBPixel *transp = NULL);
/// Same but apply Floyd-Steinberg dithering for nicer (but slower) results
extern void shQuantizeRemapDither (SRGBPixel *image, int pixels, int pixperline,
SRGBPixel *palette, int colors, byte *&outimage, SRGBPixel *transp = NULL);
#endif // __QUANTIZE_H__

View File

@@ -0,0 +1,216 @@
#ifndef __SHENDIAN_H__
#define __SHENDIAN_H__
#define CS_LITTLE_ENDIAN
/*
* This is a bit of overkill but if you're sure your CPU doesn't require
* strict alignment add your CPU to the !defined below to get slightly
* smaller and faster code in some cases.
*/
#if !defined (PROC_INTEL)
# define PROC_NEEDS_STRICT_ALIGNMENT
#endif
struct swap_4
{
unsigned char b1, b2, b3, b4;
};
#ifdef CS_BIG_ENDIAN
# define big_endian_long(x) x
# define big_endian_short(x) x
# define big_endian_float(x) x
#else
/// Convert a long from big-endian to machine format
static inline unsigned long big_endian_long (unsigned long l)
{ return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
/// Convert a short from big-endian to machine format
static inline ushort big_endian_short (ushort s)
{ return (s >> 8) | (s << 8); }
/// Convert a big-endian floating-point number to machine format
//@@WARNING: Should be removed -- use float2long instead
static inline float big_endian_float (float f)
{
unsigned char tmp;
swap_4 *pf = (swap_4 *)&f;
tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
return f;
}
#endif // CS_BIG_ENDIAN
#ifdef CS_LITTLE_ENDIAN
# define little_endian_long(x) x
# define little_endian_short(x) x
# define little_endian_float(x) x
#else
/// Convert a long from little-endian to machine format
static inline unsigned long little_endian_long (unsigned long l)
{ return (l >> 24) | ((l >> 8) & 0xff00) | ((l << 8) & 0xff0000) | (l << 24); }
/// Convert a short from little-endian to machine format
static inline ushort little_endian_short (ushort s)
{ return (s >> 8) | (s << 8); }
/// Convert a little-endian floating-point number to machine format
static inline float little_endian_float (float f)
{
unsigned char tmp;
swap_4 *pf = (swap_4 *)&f;
tmp = pf->b1; pf->b1 = pf->b4; pf->b4 = tmp;
tmp = pf->b2; pf->b2 = pf->b3; pf->b3 = tmp;
return f;
}
#endif // CS_LITTLE_ENDIAN
/*
To be able to painlessly transfer files betwen platforms, we should
avoid using native floating-point format. Here are a couple of routines
that are guaranteed to work on all platforms.
The floating point is converted to a fixed 1.7.25 bits format
(one bit sign, 7 bits exponent, 25 bits mantissa) and back,
so that we can binary store floating-point number without
cross-platform problems. If you wonder why 1+7+25 = 33 while we
only have 32 bits, we'll ommit the most significant bit of mantissa
since it is always 1 (we use normalized numbers). This increases the
precision twice.
*/
/// Convert a float to a cross-platform 32-bit format (no endianess adjustments!)
static inline long float2long (float f)
{
int exp;
long mant = QRound ((float)frexp (f, &exp) * (float)0x1000000);
long sign = mant & 0x80000000;
if (mant < 0) mant = -mant;
if (exp > 63) exp = 63; else if (exp < -64) exp = -64;
return sign | ((exp & 0x7f) << 24) | (mant & 0xffffff);
}
/// Convert a 32-bit cross-platform float to native format (no endianess adjustments!)
static inline float long2float (long l)
{
int exp = (l >> 24) & 0x7f;
if (exp & 0x40) exp = exp | ~0x7f;
float mant = float (l & 0x00ffffff) / 0x1000000;
if (l & 0x80000000) mant = -mant;
return (float)ldexp (mant, exp);
}
/**
* The following routines are used for converting floating-point numbers
* into 16-bit shorts and back. This is useful for low-precision data.
* They use the 1.4.12 format. The range of numbers that can be represented
* in this format is from 2^-8 to 2^7. The precision for numbers near to
* 2^-8 (0.00390625) is near 0.000001, for numbers near 2^7 (128) is near 0.03.
*/
/// Convert a float to a cross-platform 16-bit format (no endianess adjustments!)
static inline short float2short (float f)
{
int exp;
long mant = QRound ((float)frexp (f, &exp) * (float)0x1000);
long sign = mant & 0x8000;
if (mant < 0) mant = -mant;
if (exp > 7) mant = 0x7ff, exp = 7; else if (exp < -8) mant = 0, exp = -8;
return (short)(sign | ((exp & 0xf) << 11) | (mant & 0x7ff));
}
/// Convert a 16-bit cross-platform float to native format (no endianess adjustments!)
static inline float short2float (short s)
{
int exp = (s >> 11) & 0xf;
if (exp & 0x8) exp = exp | ~0xf;
float mant = float ((s & 0x07ff) | 0x0800) / 0x1000;
if (s & 0x8000) mant = -mant;
return (float)ldexp (mant, exp);
}
/// Swap the bytes in a unsigned long value.
static inline unsigned long convert_endian (unsigned long l)
{ return little_endian_long (l); }
/// Swap the bytes in a long value.
static inline long convert_endian (long l)
{ return little_endian_long (l); }
/// Swap the bytes in a int value.
static inline int convert_endian (int i)
{ return little_endian_long (i); }
/// Swap the bytes in a short value.
static inline ushort convert_endian (ushort s)
{ return little_endian_short (s); }
/// Swap the bytes in a float value.
static inline float convert_endian (float f)
{ return little_endian_float (f); }
/// Read a little-endian short from address
inline ushort get_le_short (void *buff)
{
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
ushort s; memcpy (&s, buff, sizeof (s));
return little_endian_short (s);
#else
return little_endian_short (*(ushort *)buff);
#endif
}
/// Read a little-endian long from address
inline unsigned long get_le_long (void *buff)
{
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
unsigned long l; memcpy (&l, buff, sizeof (l));
return little_endian_long (l);
#else
return little_endian_long (*(unsigned long *)buff);
#endif
}
/// Read a little-endian 32-bit float from address
inline float get_le_float32 (void *buff)
{ unsigned long l = get_le_long (buff); return long2float (l); }
/// Read a little-endian 16-bit float from address
inline float get_le_float16 (void *buff)
{ ushort s = get_le_short (buff); return short2float (s); }
/// Set a little-endian short on a address
inline void set_le_short (void *buff, ushort s)
{
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
s = little_endian_short (s);
memcpy (buff, &s, sizeof (s));
#else
*((ushort *)buff) = little_endian_short (s);
#endif
}
/// Set a little-endian long on a address
inline void set_le_long (void *buff, unsigned long l)
{
#ifdef PROC_NEEDS_STRICT_ALIGNMENT
l = little_endian_long (l);
memcpy (buff, &l, sizeof (l));
#else
*((unsigned long *)buff) = little_endian_long (l);
#endif
}
/// Set a little-endian 32-bit float on a address
inline void set_le_float32 (void *buff, float f)
{ set_le_long (buff, float2long (f)); }
/// Set a little-endian 16-bit float on a address
inline void set_le_float16 (void *buff, float f)
{ set_le_short (buff, float2short (f)); }
#endif // __SHENDIAN_H__

View File

@@ -0,0 +1,553 @@
/*=============================================================================
TgaImage.cpp : TGA image file format implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "CImage.h"
#include "TgaImage.h"
#define MAXCOLORS 16384
static int mapped, rlencoded;
static SRGBPixel ColorMap[MAXCOLORS];
static int RLE_count = 0, RLE_flag = 0;
static void readtga ( byte*& ptr, struct SImageHeader* tgaP );
static void get_map_entry ( byte*& ptr, SRGBPixel* Value, int Size );
static void get_pixel ( byte*& ptr, SRGBPixel* dest, int Size );
static byte getbyte ( byte*& ptr );
CImageTgaFile::~CImageTgaFile ()
{
}
CImageTgaFile::CImageTgaFile (byte* ptr, long filesize) : CImageFile ()
{
(void)filesize;
struct SImageHeader tga_head;
int i;
unsigned int temp1, temp2;
int rows, cols, row, col, realrow, truerow, baserow;
int maxval;
SRGBPixel *pixels;
/* @@@ to do: Add TGA format detection */
/* Read the Targa file header. */
readtga (ptr, &tga_head);
rows = ( (int) tga_head.Height_lo ) + ( (int) tga_head.Height_hi ) * 256;
cols = ( (int) tga_head.Width_lo ) + ( (int) tga_head.Width_hi ) * 256;
m_eFormat = eIF_Tga;
switch ( tga_head.ImgType )
{
case TGA_Map:
case TGA_RGB:
case TGA_Mono:
case TGA_RLEMap:
case TGA_RLERGB:
case TGA_RLEMono:
break;
default:
mfSet_error (eIFE_BadFormat, "Unknown Targa image type");
return;
}
if ( tga_head.ImgType == TGA_Map ||
tga_head.ImgType == TGA_RLEMap ||
tga_head.ImgType == TGA_CompMap ||
tga_head.ImgType == TGA_CompMap4 )
{ /* Color-mapped image */
if ( tga_head.CoMapType != 1 )
{
mfSet_error (eIFE_BadFormat, "Mapped image with bad color map type");
return;
}
mapped = 1;
/* Figure maxval from CoSize. */
switch ( tga_head.CoSize )
{
case 8:
case 24:
case 32:
maxval = 255;
break;
case 15:
case 16:
maxval = 31;
break;
default:
mfSet_error (eIFE_BadFormat, "Unknown colormap pixel size");
return;
}
}
else
{ /* Not colormap, so figure maxval from PixelSize. */
mapped = 0;
switch ( tga_head.PixelSize )
{
case 8:
case 24:
case 32:
maxval = 255;
break;
case 15:
case 16:
maxval = 31;
break;
default:
mfSet_error (eIFE_BadFormat, "Unknown pixel size");
return;
}
}
mfSet_bps(tga_head.PixelSize);
/* If required, read the color map information. */
if ( tga_head.CoMapType != 0 )
{
temp1 = tga_head.Index_lo + tga_head.Index_hi * 256;
temp2 = tga_head.Length_lo + tga_head.Length_hi * 256;
if ( ( temp1 + temp2 + 1 ) >= MAXCOLORS )
{
mfSet_error (eIFE_BadFormat, "Too many colors in colormap");
return;
}
for ( i = temp1; i < (int)( temp1 + temp2 ); ++i )
get_map_entry( ptr, &ColorMap[i], (int) tga_head.CoSize );
}
/* Check run-length encoding. */
if ( tga_head.ImgType == TGA_RLEMap || tga_head.ImgType == TGA_RLERGB || tga_head.ImgType == TGA_RLEMono )
rlencoded = 1;
else
rlencoded = 0;
/* Read the Targa file body and convert to portable format. */
mfSet_dimensions (cols, rows);
mfSet_ImageSize(cols * rows * 4);
pixels = (SRGBPixel *)mfGet_image();
truerow = 0;
baserow = 0;
for ( row = 0; row < rows; ++row )
{
realrow = truerow;
if ( tga_head.OrgBit == 0 )
realrow = rows - realrow - 1;
for ( col = 0; col < cols; ++col )
get_pixel( ptr, &(pixels[realrow*cols+col]), (int) tga_head.PixelSize );
if ( tga_head.IntrLve == TGA_IL_Four )
truerow += 4;
else
if ( tga_head.IntrLve == TGA_IL_Two )
truerow += 2;
else
++truerow;
if ( truerow >= rows )
truerow = ++baserow;
}
}
static void readtga (byte*& ptr, SImageHeader* tgaP)
{
byte flags;
tgaP->IDLength = getbyte( ptr );
tgaP->CoMapType = getbyte( ptr );
tgaP->ImgType = getbyte( ptr );
tgaP->Index_lo = getbyte( ptr );
tgaP->Index_hi = getbyte( ptr );
tgaP->Length_lo = getbyte( ptr );
tgaP->Length_hi = getbyte( ptr );
tgaP->CoSize = getbyte( ptr );
tgaP->X_org_lo = getbyte( ptr );
tgaP->X_org_hi = getbyte( ptr );
tgaP->Y_org_lo = getbyte( ptr );
tgaP->Y_org_hi = getbyte( ptr );
tgaP->Width_lo = getbyte( ptr );
tgaP->Width_hi = getbyte( ptr );
tgaP->Height_lo = getbyte( ptr );
tgaP->Height_hi = getbyte( ptr );
tgaP->PixelSize = getbyte( ptr );
flags = getbyte( ptr );
tgaP->AttBits = flags & 0xf;
tgaP->Rsrvd = ( flags & 0x10 ) >> 4;
tgaP->OrgBit = ( flags & 0x20 ) >> 5;
tgaP->IntrLve = ( flags & 0xc0 ) >> 6;
if ( tgaP->IDLength != 0 )
ptr += tgaP->IDLength;
}
static void get_map_entry (byte*& ptr, SRGBPixel* Value, int Size)
{
byte j, k, r, g, b;
r=g=b=0; /* get rid of 'might be used uninited' warning */
/* Read appropriate number of bytes, break into rgb & put in map. */
switch ( Size )
{
case 8: /* Grey scale, read and triplicate. */
r = g = b = getbyte( ptr );
break;
case 16: /* 5 bits each of red green and blue. */
case 15: /* Watch for byte order. */
j = getbyte( ptr );
k = getbyte( ptr );
r = ( k & 0x7C ) >> 2;
g = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
b = j & 0x1F;
break;
case 32:
case 24: /* 8 bits each of blue green and red. */
b = getbyte( ptr );
g = getbyte( ptr );
r = getbyte( ptr );
if ( Size == 32 )
(void) getbyte( ptr ); /* Read alpha byte & throw away. */
break;
default:
//mfSet_error (eIFE_BadFormat, "Unknown colormap pixel size");
return;
}
Value->red=r; Value->green=g; Value->blue=b;
}
static void get_pixel (byte*& ptr, SRGBPixel* dest, int Size)
{
static int Red, Grn, Blu, Alpha;
byte j, k;
static unsigned int l;
if (Size != 32)
Alpha = 255;
/* Check if run length encoded. */
if ( rlencoded )
{
if ( RLE_count == 0 )
{ /* Have to restart run. */
byte i;
i = getbyte( ptr );
RLE_flag = ( i & 0x80 );
if ( RLE_flag == 0 )
/* Stream of unencoded pixels. */
RLE_count = i + 1;
else
/* Single pixel replicated. */
RLE_count = i - 127;
/* Decrement count & get pixel. */
--RLE_count;
}
else
{ /* Have already read count & (at least) first pixel. */
--RLE_count;
if ( RLE_flag != 0 )
/* Replicated pixels. */
goto PixEncode;
}
}
/* Read appropriate number of bytes, break into RGB. */
switch ( Size )
{
case 8: /* Grey scale, read and triplicate. */
Red = Grn = Blu = l = getbyte( ptr );
break;
case 16: /* 5 bits each of red green and blue. */
case 15: /* Watch byte order. */
j = getbyte( ptr );
k = getbyte( ptr );
l = ( (unsigned int) k << 8 ) + j;
Red = ( k & 0x7C ) >> 2;
Grn = ( ( k & 0x03 ) << 3 ) + ( ( j & 0xE0 ) >> 5 );
Blu = j & 0x1F;
break;
case 32:
case 24: /* 8 bits each of blue green and red. */
Blu = getbyte( ptr );
Grn = getbyte( ptr );
Red = getbyte( ptr );
if ( Size == 32 )
Alpha = getbyte( ptr ); /* Read alpha byte & throw away. */
l = 0;
break;
default:
//mfSet_error (eIFE_BadFormat, "Unknown pixel size");
return;
}
PixEncode:
if ( mapped )
*dest = ColorMap[l];
else
{
dest->red=Red;dest->green=Grn;dest->blue=Blu;
dest->alpha = Alpha;
}
}
static byte getbyte (byte*& ptr)
{
byte c = *ptr++;
return c;
}
//=============================================================
#if !defined(LINUX)
#include <io.h>
#include <fcntl.h>
#endif
static FILE *sFileData;
static int src_bits_per_pixel;
static void bwrite(unsigned char data)
{
fputc(data, sFileData);
}
void wwrite(unsigned short data)
{
unsigned char h, l;
l = data & 0xFF;
h = data >> 8;
bwrite(l);
bwrite(h);
}
static void WritePixel(int depth, unsigned long a, unsigned long r, unsigned long g, unsigned long b)
{
DWORD color16;
switch(depth)
{
case 32:
bwrite((byte)b); // b
bwrite((byte)g); // g
bwrite((byte)r); // r
bwrite((byte)a); // a
break;
case 24:
bwrite((byte)b); // b
bwrite((byte)g); // g
bwrite((byte)r); // r
break;
case 16:
r >>= 3;
g >>= 3;
b >>= 3;
r &= 0x1F;
g &= 0x1F;
b &= 0x1F;
color16 = (r << 10) | (g << 5) | b;
wwrite((unsigned short)color16);
break;
}
}
static void GetPixel(unsigned char * data, int depth, unsigned long &a, unsigned long &r, unsigned long &g, unsigned long &b)
{
switch(depth)
{
case 32:
r = *data++;
g = *data++;
b = *data++;
a = *data++;
break;
case 24:
r = *data++;
g = *data++;
b = *data++;
a = 0xFF;
break;
default:
assert(0);
break;
}
}
void WriteTGA8(byte *data8, int width, int height, char *filename)
{
unsigned char * data32 = new unsigned char [width*height*4];
for(int i=0; i<width*height; i++)
{
data32[i*4+0] = data8[i];
data32[i*4+1] = data8[i];
data32[i*4+2] = data8[i];
data32[i*4+3] = 255;
}
WriteTGA(data32, width, height, filename, 32);
delete [] data32;
}
void WriteTGA(byte *data, int width, int height, char *filename, int dest_bits_per_pixel)
{
#ifndef PS2
int i;
unsigned long r,g,b,a;
src_bits_per_pixel = 32;
if ((sFileData = fopen(filename, "wb")) == NULL)
return;
//mdesc |= LR; // left right
//m_desc |= UL_TGA_BT; // top
int id_length = 0;
int x_org = 0;
int y_org = 0;
int desc = 0;
// 32 bpp
int cm_index = 0;
int cm_length = 0;
int cm_entry_size = 0;
int color_map_type = 0;
int type = 2;
bwrite(id_length);
bwrite(color_map_type);
bwrite(type);
wwrite(cm_index);
wwrite(cm_length);
bwrite(cm_entry_size);
wwrite(x_org);
wwrite(y_org);
wwrite((unsigned short) width);
wwrite((unsigned short) height);
bwrite( dest_bits_per_pixel );
bwrite(desc);
int hxw = height * width;
int right = 0;
int top = 1;
DWORD * temp_dp = (DWORD*) data; // data = input pointer
DWORD * swap = 0;
if( !top )
{
assert( src_bits_per_pixel == 32 );
swap = (DWORD *) new DWORD[ hxw ];
// copy whole image data to swap buffer
cryMemcpy(swap, temp_dp, hxw * sizeof( DWORD ));
DWORD * src, * dest;
for (i = 0; i < height; i++)
{
// copy lines from old into new buffer
src = & temp_dp[ ( height - i - 1) * width ];
dest = & swap[ i * width ];
cryMemcpy(dest, src, width * sizeof(DWORD) );
}
// use the swapped area in further processing & to write out the data
data = (unsigned char *)swap;
}
UINT src_bytes_per_pixel = src_bits_per_pixel / 8;
UINT size_in_bytes = hxw * src_bytes_per_pixel;
if( src_bits_per_pixel == dest_bits_per_pixel)
{
fwrite(data, hxw, src_bytes_per_pixel, sFileData);
}
else
{
for (i = 0; i < hxw; i++)
{
GetPixel( data, src_bits_per_pixel, a, b, g, r);
WritePixel( dest_bits_per_pixel, a, b, g, r);
data += src_bytes_per_pixel;
}
}
fclose(sFileData);
SAFE_DELETE_ARRAY(swap);
#else
OutputDebugString("Not Implemented");
#endif
}
void BlurImage8(byte * pImage, int nSize, int nPassesNum)
{
#define DATA_TMP(_x,_y) (pTemp [(_x)+nSize*(_y)])
#define DATA_IMG(_x,_y) (pImage[(_x)+nSize*(_y)])
byte * pTemp = new byte [nSize*nSize];
for(int nPass=0; nPass<nPassesNum; nPass++)
{
cryMemcpy(pTemp,pImage,nSize*nSize);
for(int x=1; x<nSize-1; x++)
for(int y=1; y<nSize-1; y++)
{
float fVal = 0;
fVal += DATA_TMP(x,y);
fVal += DATA_TMP(x+1,y+1);
fVal += DATA_TMP(x-1,y+1);
fVal += DATA_TMP(x+1,y-1);
fVal += DATA_TMP(x-1,y-1);
DATA_IMG(x,y) = uchar(fVal*0.2f);
}
}
delete [] pTemp;
#undef DATA_IMG
#undef DATA_TMP
}

View File

@@ -0,0 +1,60 @@
#ifndef TGAIMAGE_H
#define TGAIMAGE_H
/**
* An ImageFile subclass for reading TGA files.
*/
class CImageTgaFile : public CImageFile
{
///
friend class CImageFile; // For constructor
private:
/// Read the TGA file from the buffer.
CImageTgaFile (byte* buf, long size);
public:
///
virtual ~CImageTgaFile ();
};
/* Header definition. */
struct SImageHeader {
unsigned char IDLength; /* length of Identifier String */
unsigned char CoMapType; /* 0 = no map */
unsigned char ImgType; /* image type (see below for values) */
unsigned char Index_lo, Index_hi; /* index of first color map entry */
unsigned char Length_lo, Length_hi; /* number of entries in color map */
unsigned char CoSize; /* size of color map entry (15,16,24,32) */
unsigned char X_org_lo, X_org_hi; /* x origin of image */
unsigned char Y_org_lo, Y_org_hi; /* y origin of image */
unsigned char Width_lo, Width_hi; /* width of image */
unsigned char Height_lo, Height_hi; /* height of image */
unsigned char PixelSize; /* pixel size (8,16,24,32) */
unsigned char AttBits; /* 4 bits, number of attribute bits per pixel */
unsigned char Rsrvd; /* 1 bit, reserved */
unsigned char OrgBit; /* 1 bit, origin: 0=lower left, 1=upper left */
unsigned char IntrLve; /* 2 bits, interleaving flag */
};
typedef char ImageIDField[256];
/* Definitions for image types. */
#define TGA_Null 0
#define TGA_Map 1
#define TGA_RGB 2
#define TGA_Mono 3
#define TGA_RLEMap 9
#define TGA_RLERGB 10
#define TGA_RLEMono 11
#define TGA_CompMap 32
#define TGA_CompMap4 33
/* Definitions for interleave flag. */
#define TGA_IL_None 0
#define TGA_IL_Two 1
#define TGA_IL_Four 2
#endif

Some files were not shown because too many files have changed in this diff Show More