forked from Mirrors/openclonk
Avoid built-in GL matrices for mesh rendering
Instead, compute the projection, modelview and normal matrices explictly and upload them as shader uniforms.shapetextures
parent
a487457563
commit
de3ed60aa8
|
@ -38,6 +38,10 @@
|
||||||
|
|
||||||
varying vec3 normalDir;
|
varying vec3 normalDir;
|
||||||
|
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat4 modelviewMatrix;
|
||||||
|
uniform mat3 normalMatrix;
|
||||||
|
|
||||||
#ifndef OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS
|
#ifndef OC_WA_LOW_MAX_VERTEX_UNIFORM_COMPONENTS
|
||||||
uniform mat4x3 bones[MAX_BONE_COUNT];
|
uniform mat4x3 bones[MAX_BONE_COUNT];
|
||||||
#else
|
#else
|
||||||
|
@ -72,7 +76,7 @@ vec4 merge_bone(vec4 vertex, vec4 original, mat3x4 bone, float weight)
|
||||||
slice(position)
|
slice(position)
|
||||||
{
|
{
|
||||||
#if BONE_COUNT == 0
|
#if BONE_COUNT == 0
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
gl_Position = projectionMatrix * modelviewMatrix * gl_Vertex;
|
||||||
#else
|
#else
|
||||||
vec4 vertex = vec4(0, 0, 0, 0);
|
vec4 vertex = vec4(0, 0, 0, 0);
|
||||||
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices0.x)], oc_BoneWeights0.x);
|
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices0.x)], oc_BoneWeights0.x);
|
||||||
|
@ -85,7 +89,7 @@ slice(position)
|
||||||
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
||||||
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
vertex = merge_bone(vertex, gl_Vertex, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
||||||
#endif
|
#endif
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * vertex;
|
gl_Position = projectionMatrix * modelviewMatrix * vertex;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +101,7 @@ slice(texcoord)
|
||||||
slice(normal)
|
slice(normal)
|
||||||
{
|
{
|
||||||
#if BONE_COUNT == 0
|
#if BONE_COUNT == 0
|
||||||
normalDir = normalize(gl_NormalMatrix * gl_Normal);
|
normalDir = normalize(normalMatrix * gl_Normal);
|
||||||
#else
|
#else
|
||||||
vec4 base_normal = vec4(gl_Normal, 0.0);
|
vec4 base_normal = vec4(gl_Normal, 0.0);
|
||||||
vec4 normal = vec4(0, 0, 0, 0);
|
vec4 normal = vec4(0, 0, 0, 0);
|
||||||
|
@ -111,6 +115,6 @@ slice(normal)
|
||||||
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.z)], oc_BoneWeights1.z);
|
||||||
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
normal = merge_bone(normal, base_normal, bones[int(oc_BoneIndices1.w)], oc_BoneWeights1.w);
|
||||||
#endif
|
#endif
|
||||||
normalDir = normalize(gl_NormalMatrix * normal.xyz);
|
normalDir = normalize(normalMatrix * normal.xyz);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,13 +70,7 @@ slice(normal)
|
||||||
#ifdef OC_WITH_NORMALMAP
|
#ifdef OC_WITH_NORMALMAP
|
||||||
vec4 normalPx = texture2D(normalTex, texcoord.xy);
|
vec4 normalPx = texture2D(normalTex, texcoord.xy);
|
||||||
vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5));
|
vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5));
|
||||||
#ifdef OC_MESH
|
|
||||||
// TODO: Change to normalMatrix once we changed mesh rendering
|
|
||||||
// to use custom matrices
|
|
||||||
vec3 normal = normalize(gl_NormalMatrix * normalPxDir);
|
|
||||||
#else
|
|
||||||
vec3 normal = normalize(normalMatrix * normalPxDir);
|
vec3 normal = normalize(normalMatrix * normalPxDir);
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#ifdef OC_MESH
|
#ifdef OC_MESH
|
||||||
vec3 normal = normalDir; // Normal matrix is already applied in vertex shader
|
vec3 normal = normalDir; // Normal matrix is already applied in vertex shader
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
uniform sampler2D basemap;
|
uniform sampler2D basemap;
|
||||||
uniform sampler2D normalTex;
|
uniform sampler2D normalTex;
|
||||||
|
uniform mat3 normalMatrix;
|
||||||
|
|
||||||
#ifndef OPENCLONK
|
#ifndef OPENCLONK
|
||||||
#define slice(x)
|
#define slice(x)
|
||||||
|
@ -12,9 +13,6 @@ void main()
|
||||||
|
|
||||||
slice(texture+1)
|
slice(texture+1)
|
||||||
{
|
{
|
||||||
// This picks up the normal map lookup in ObjectLightShader.c:
|
|
||||||
#define OC_WITH_NORMALMAP
|
|
||||||
|
|
||||||
color = color * texture2D(basemap, texcoord);
|
color = color * texture2D(basemap, texcoord);
|
||||||
|
|
||||||
#ifndef OPENCLONK
|
#ifndef OPENCLONK
|
||||||
|
@ -23,6 +21,17 @@ slice(texture+1)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slice(normal+1)
|
||||||
|
{
|
||||||
|
// TODO: This overrides what is set in slice(normal)
|
||||||
|
// from ObjectShader.glsl. It's probably optimized out,
|
||||||
|
// but a more elegant solution would be nice. Also maybe
|
||||||
|
// a function in UtilShader.glsl to reduce code duplication.
|
||||||
|
vec4 normalPx = texture2D(normalTex, texcoord.xy);
|
||||||
|
vec3 normalPxDir = 2.0 * (normalPx.xyz - vec3(0.5, 0.5, 0.5));
|
||||||
|
normal = normalize(normalMatrix * normalPxDir);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef OPENCLONK
|
#ifndef OPENCLONK
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat4 modelviewMatrix;
|
||||||
|
|
||||||
|
varying vec3 normalDir;
|
||||||
|
|
||||||
#ifndef OPENCLONK
|
#ifndef OPENCLONK
|
||||||
#define slice(x)
|
#define slice(x)
|
||||||
varying vec2 texcoord;
|
varying vec2 texcoord;
|
||||||
|
@ -11,9 +16,16 @@ slice(texcoord)
|
||||||
texcoord = gl_MultiTexCoord0.xy;
|
texcoord = gl_MultiTexCoord0.xy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slice(normal)
|
||||||
|
{
|
||||||
|
// Dummy variable, it's not used in the fragment shader.
|
||||||
|
// TODO: Improve construction of shaders so this is not needed.
|
||||||
|
normalDir = vec3(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
slice(position)
|
slice(position)
|
||||||
{
|
{
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
gl_Position = projectionMatrix * modelviewMatrix * gl_Vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENCLONK
|
#ifndef OPENCLONK
|
||||||
|
|
|
@ -35,12 +35,18 @@ namespace
|
||||||
// to an equivalent fragment shader. The generated code can certainly
|
// to an equivalent fragment shader. The generated code can certainly
|
||||||
// be optimized more.
|
// be optimized more.
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
StdStrBuf TextureUnitSourceToCode(int index, StdMeshMaterialTextureUnit::BlendOpSourceType source, const float manualColor[3], float manualAlpha)
|
StdStrBuf Texture2DToCode(int index, bool hasTextureAnimation)
|
||||||
|
{
|
||||||
|
if (hasTextureAnimation) return FormatString("texture2D(oc_Texture%d, (oc_TextureMatrix%d * vec4(texcoord, 0.0, 1.0)).xy)", index, index);
|
||||||
|
return FormatString("texture2D(oc_Texture%d, texcoord)", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
StdStrBuf TextureUnitSourceToCode(int index, StdMeshMaterialTextureUnit::BlendOpSourceType source, const float manualColor[3], float manualAlpha, bool hasTextureAnimation)
|
||||||
{
|
{
|
||||||
switch(source)
|
switch(source)
|
||||||
{
|
{
|
||||||
case StdMeshMaterialTextureUnit::BOS_Current: return StdStrBuf("currentColor");
|
case StdMeshMaterialTextureUnit::BOS_Current: return StdStrBuf("currentColor");
|
||||||
case StdMeshMaterialTextureUnit::BOS_Texture: return FormatString("texture2D(oc_Texture%d, texcoord)", index);
|
case StdMeshMaterialTextureUnit::BOS_Texture: return Texture2DToCode(index, hasTextureAnimation);
|
||||||
case StdMeshMaterialTextureUnit::BOS_Diffuse: return StdStrBuf("diffuse");
|
case StdMeshMaterialTextureUnit::BOS_Diffuse: return StdStrBuf("diffuse");
|
||||||
case StdMeshMaterialTextureUnit::BOS_Specular: return StdStrBuf("diffuse"); // TODO: Should be specular
|
case StdMeshMaterialTextureUnit::BOS_Specular: return StdStrBuf("diffuse"); // TODO: Should be specular
|
||||||
case StdMeshMaterialTextureUnit::BOS_PlayerColor: return StdStrBuf("vec4(oc_PlayerColor, 1.0)");
|
case StdMeshMaterialTextureUnit::BOS_PlayerColor: return StdStrBuf("vec4(oc_PlayerColor, 1.0)");
|
||||||
|
@ -49,7 +55,7 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStrBuf TextureUnitBlendToCode(int index, StdMeshMaterialTextureUnit::BlendOpExType blend_type, const char* source1, const char* source2, float manualFactor)
|
StdStrBuf TextureUnitBlendToCode(int index, StdMeshMaterialTextureUnit::BlendOpExType blend_type, const char* source1, const char* source2, float manualFactor, bool hasTextureAnimation)
|
||||||
{
|
{
|
||||||
switch(blend_type)
|
switch(blend_type)
|
||||||
{
|
{
|
||||||
|
@ -63,10 +69,10 @@ namespace
|
||||||
case StdMeshMaterialTextureUnit::BOX_AddSmooth: return FormatString("%s + %s - %s*%s", source1, source2, source1, source2);
|
case StdMeshMaterialTextureUnit::BOX_AddSmooth: return FormatString("%s + %s - %s*%s", source1, source2, source1, source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_Subtract: return FormatString("%s - %s", source1, source2);
|
case StdMeshMaterialTextureUnit::BOX_Subtract: return FormatString("%s - %s", source1, source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_BlendDiffuseAlpha: return FormatString("diffuse.a * %s + (1.0 - diffuse.a) * %s", source1, source2);
|
case StdMeshMaterialTextureUnit::BOX_BlendDiffuseAlpha: return FormatString("diffuse.a * %s + (1.0 - diffuse.a) * %s", source1, source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_BlendTextureAlpha: return FormatString("texture2D(oc_Texture%d, texcoord).a * %s + (1.0 - texture2D(oc_Texture%d, texcoord).a) * %s", index, source1, index, source2);
|
case StdMeshMaterialTextureUnit::BOX_BlendTextureAlpha: return FormatString("%s.a * %s + (1.0 - %s.a) * %s", Texture2DToCode(index, hasTextureAnimation).getData(), source1, Texture2DToCode(index, hasTextureAnimation).getData(), source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_BlendCurrentAlpha: return FormatString("currentColor.a * %s + (1.0 - currentColor.a) * %s", source1, source2);
|
case StdMeshMaterialTextureUnit::BOX_BlendCurrentAlpha: return FormatString("currentColor.a * %s + (1.0 - currentColor.a) * %s", source1, source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_BlendManual: return FormatString("%f * %s + (1.0 - %f) * %s", manualFactor, source1, manualFactor, source2);
|
case StdMeshMaterialTextureUnit::BOX_BlendManual: return FormatString("%f * %s + (1.0 - %f) * %s", manualFactor, source1, manualFactor, source2);
|
||||||
case StdMeshMaterialTextureUnit::BOX_Dotproduct: return FormatString("vec3(4.0 * dot(%s - 0.5, %s - 0.5), 4.0 * dot(%s - 0.5, %s - 0.5), 4.0 * dot(%s - 0.5, %s - 0.5));", source1, source2, source1, source2, source1, source2); // TODO: Needs special handling for the case of alpha
|
case StdMeshMaterialTextureUnit::BOX_Dotproduct: return FormatString("vec3(4.0 * dot(%s - 0.5, %s - 0.5), 4.0 * dot(%s - 0.5, %s - 0.5), 4.0 * dot(%s - 0.5, %s - 0.5))", source1, source2, source1, source2, source1, source2); // TODO: Needs special handling for the case of alpha
|
||||||
case StdMeshMaterialTextureUnit::BOX_BlendDiffuseColor: return FormatString("diffuse.rgb * %s + (1.0 - diffuse.rgb) * %s", source1, source2);
|
case StdMeshMaterialTextureUnit::BOX_BlendDiffuseColor: return FormatString("diffuse.rgb * %s + (1.0 - diffuse.rgb) * %s", source1, source2);
|
||||||
default: assert(false); return StdStrBuf(source1);
|
default: assert(false); return StdStrBuf(source1);
|
||||||
}
|
}
|
||||||
|
@ -74,12 +80,14 @@ namespace
|
||||||
|
|
||||||
StdStrBuf TextureUnitToCode(int index, const StdMeshMaterialTextureUnit& texunit)
|
StdStrBuf TextureUnitToCode(int index, const StdMeshMaterialTextureUnit& texunit)
|
||||||
{
|
{
|
||||||
StdStrBuf color_source1 = FormatString("%s.rgb", TextureUnitSourceToCode(index, texunit.ColorOpSources[0], texunit.ColorOpManualColor1, texunit.AlphaOpManualAlpha1).getData());
|
const bool hasTextureAnimation = texunit.HasTexCoordAnimation();
|
||||||
StdStrBuf color_source2 = FormatString("%s.rgb", TextureUnitSourceToCode(index, texunit.ColorOpSources[1], texunit.ColorOpManualColor2, texunit.AlphaOpManualAlpha2).getData());
|
|
||||||
StdStrBuf alpha_source1 = FormatString("%s.a", TextureUnitSourceToCode(index, texunit.AlphaOpSources[0], texunit.ColorOpManualColor1, texunit.AlphaOpManualAlpha1).getData());
|
|
||||||
StdStrBuf alpha_source2 = FormatString("%s.a", TextureUnitSourceToCode(index, texunit.AlphaOpSources[1], texunit.ColorOpManualColor2, texunit.AlphaOpManualAlpha2).getData());
|
|
||||||
|
|
||||||
return FormatString("currentColor = vec4(%s, %s);\n", TextureUnitBlendToCode(index, texunit.ColorOpEx, color_source1.getData(), color_source2.getData(), texunit.ColorOpManualFactor).getData(), TextureUnitBlendToCode(index, texunit.AlphaOpEx, alpha_source1.getData(), alpha_source2.getData(), texunit.AlphaOpManualFactor).getData());
|
StdStrBuf color_source1 = FormatString("%s.rgb", TextureUnitSourceToCode(index, texunit.ColorOpSources[0], texunit.ColorOpManualColor1, texunit.AlphaOpManualAlpha1, hasTextureAnimation).getData());
|
||||||
|
StdStrBuf color_source2 = FormatString("%s.rgb", TextureUnitSourceToCode(index, texunit.ColorOpSources[1], texunit.ColorOpManualColor2, texunit.AlphaOpManualAlpha2, hasTextureAnimation).getData());
|
||||||
|
StdStrBuf alpha_source1 = FormatString("%s.a", TextureUnitSourceToCode(index, texunit.AlphaOpSources[0], texunit.ColorOpManualColor1, texunit.AlphaOpManualAlpha1, hasTextureAnimation).getData());
|
||||||
|
StdStrBuf alpha_source2 = FormatString("%s.a", TextureUnitSourceToCode(index, texunit.AlphaOpSources[1], texunit.ColorOpManualColor2, texunit.AlphaOpManualAlpha2, hasTextureAnimation).getData());
|
||||||
|
|
||||||
|
return FormatString("currentColor = vec4(%s, %s);\n", TextureUnitBlendToCode(index, texunit.ColorOpEx, color_source1.getData(), color_source2.getData(), texunit.ColorOpManualFactor, hasTextureAnimation).getData(), TextureUnitBlendToCode(index, texunit.AlphaOpEx, alpha_source1.getData(), alpha_source2.getData(), texunit.AlphaOpManualFactor, hasTextureAnimation).getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStrBuf AlphaTestToCode(const StdMeshMaterialPass& pass)
|
StdStrBuf AlphaTestToCode(const StdMeshMaterialPass& pass)
|
||||||
|
@ -136,10 +144,13 @@ namespace
|
||||||
// Fall back just in case
|
// Fall back just in case
|
||||||
buf.Copy(
|
buf.Copy(
|
||||||
"varying vec3 normalDir;\n"
|
"varying vec3 normalDir;\n"
|
||||||
|
"uniform mat4 projectionMatrix;\n"
|
||||||
|
"uniform mat4 modelviewMatrix;\n"
|
||||||
|
"uniform mat3 normalMatrix;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"slice(position)\n"
|
"slice(position)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
" gl_Position = projectionMatrix * modelviewMatrix * gl_Vertex;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"slice(texcoord)\n"
|
"slice(texcoord)\n"
|
||||||
|
@ -149,7 +160,7 @@ namespace
|
||||||
"\n"
|
"\n"
|
||||||
"slice(normal)\n"
|
"slice(normal)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" normalDir = normalize(gl_NormalMatrix * gl_Normal);\n"
|
" normalDir = normalize(normalMatrix * gl_Normal);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +191,15 @@ namespace
|
||||||
{
|
{
|
||||||
textureUnitDeclCode.Append(FormatString("uniform sampler2D oc_Texture%u;\n", texIndex).getData());
|
textureUnitDeclCode.Append(FormatString("uniform sampler2D oc_Texture%u;\n", texIndex).getData());
|
||||||
params.AddParameter(FormatString("oc_Texture%u", texIndex).getData(), StdMeshMaterialShaderParameter::INT).GetInt() = texIndex;
|
params.AddParameter(FormatString("oc_Texture%u", texIndex).getData(), StdMeshMaterialShaderParameter::INT).GetInt() = texIndex;
|
||||||
|
|
||||||
|
// If the texture unit has texture coordinate transformations,
|
||||||
|
// add a corresponding texture matrix uniform.
|
||||||
|
if(texunit.HasTexCoordAnimation())
|
||||||
|
{
|
||||||
|
textureUnitDeclCode.Append(FormatString("uniform mat4 oc_TextureMatrix%u;\n", texIndex).getData());
|
||||||
|
params.AddParameter(FormatString("oc_TextureMatrix%u", texIndex).getData(), StdMeshMaterialShaderParameter::AUTO_TEXTURE_MATRIX).GetInt() = texIndex;
|
||||||
|
}
|
||||||
|
|
||||||
++texIndex;
|
++texIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,21 +351,6 @@ bool CStdGL::PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoad
|
||||||
technique.Available = false;
|
technique.Available = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int m = 0; m < texunit.Transformations.size(); ++m)
|
|
||||||
{
|
|
||||||
StdMeshMaterialTextureUnit::Transformation& trans = texunit.Transformations[m];
|
|
||||||
if (trans.TransformType == StdMeshMaterialTextureUnit::Transformation::T_TRANSFORM)
|
|
||||||
{
|
|
||||||
// transpose so we can directly pass it to glMultMatrixf
|
|
||||||
std::swap(trans.Transform.M[ 1], trans.Transform.M[ 4]);
|
|
||||||
std::swap(trans.Transform.M[ 2], trans.Transform.M[ 8]);
|
|
||||||
std::swap(trans.Transform.M[ 3], trans.Transform.M[12]);
|
|
||||||
std::swap(trans.Transform.M[ 6], trans.Transform.M[ 9]);
|
|
||||||
std::swap(trans.Transform.M[ 7], trans.Transform.M[13]);
|
|
||||||
std::swap(trans.Transform.M[11], trans.Transform.M[14]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // loop over textures
|
} // loop over textures
|
||||||
} // loop over texture units
|
} // loop over texture units
|
||||||
|
|
||||||
|
@ -418,27 +423,44 @@ namespace
|
||||||
{
|
{
|
||||||
// Apply Zoom and Transformation to the current matrix stack. Return
|
// Apply Zoom and Transformation to the current matrix stack. Return
|
||||||
// parity of the transformation.
|
// parity of the transformation.
|
||||||
bool ApplyZoomAndTransform(float ZoomX, float ZoomY, float Zoom, C4BltTransform* pTransform)
|
bool ApplyZoomAndTransform(float ZoomX, float ZoomY, float Zoom, C4BltTransform* pTransform, StdProjectionMatrix& projection)
|
||||||
{
|
{
|
||||||
// Apply zoom
|
// Apply zoom
|
||||||
glTranslatef(ZoomX, ZoomY, 0.0f);
|
Translate(projection, ZoomX, ZoomY, 0.0f);
|
||||||
glScalef(Zoom, Zoom, 1.0f);
|
Scale(projection, Zoom, Zoom, 1.0f);
|
||||||
glTranslatef(-ZoomX, -ZoomY, 0.0f);
|
Translate(projection, -ZoomX, -ZoomY, 0.0f);
|
||||||
|
|
||||||
// Apply transformation
|
// Apply transformation
|
||||||
if (pTransform)
|
if (pTransform)
|
||||||
{
|
{
|
||||||
const GLfloat transform[16] = { pTransform->mat[0], pTransform->mat[3], 0, pTransform->mat[6], pTransform->mat[1], pTransform->mat[4], 0, pTransform->mat[7], 0, 0, 1, 0, pTransform->mat[2], pTransform->mat[5], 0, pTransform->mat[8] };
|
StdProjectionMatrix transform;
|
||||||
glMultMatrixf(transform);
|
transform(0, 0) = pTransform->mat[0];
|
||||||
|
transform(0, 1) = pTransform->mat[1];
|
||||||
|
transform(0, 2) = 0.0f;
|
||||||
|
transform(0, 3) = pTransform->mat[2];
|
||||||
|
transform(1, 0) = pTransform->mat[3];
|
||||||
|
transform(1, 1) = pTransform->mat[4];
|
||||||
|
transform(1, 2) = 0.0f;
|
||||||
|
transform(1, 3) = pTransform->mat[5];
|
||||||
|
transform(2, 0) = 0.0f;
|
||||||
|
transform(2, 1) = 0.0f;
|
||||||
|
transform(2, 2) = 1.0f;
|
||||||
|
transform(2, 3) = 0.0f;
|
||||||
|
transform(3, 0) = pTransform->mat[6];
|
||||||
|
transform(3, 1) = pTransform->mat[7];
|
||||||
|
transform(3, 2) = 0.0f;
|
||||||
|
transform(3, 3) = pTransform->mat[8];
|
||||||
|
projection *= transform;
|
||||||
|
|
||||||
// Compute parity of the transformation matrix - if parity is swapped then
|
// Compute parity of the transformation matrix - if parity is swapped then
|
||||||
// we need to cull front faces instead of back faces.
|
// we need to cull front faces instead of back faces.
|
||||||
const float det = transform[0]*transform[5]*transform[15]
|
const float det = transform(0,0)*transform(1,1)*transform(3,3)
|
||||||
+ transform[4]*transform[13]*transform[3]
|
+ transform(1,0)*transform(3,1)*transform(0,3)
|
||||||
+ transform[12]*transform[1]*transform[7]
|
+ transform(3,0)*transform(0,1)*transform(1,3)
|
||||||
- transform[0]*transform[13]*transform[7]
|
- transform(0,0)*transform(3,1)*transform(1,3)
|
||||||
- transform[4]*transform[1]*transform[15]
|
- transform(1,0)*transform(0,1)*transform(3,3)
|
||||||
- transform[12]*transform[5]*transform[3];
|
- transform(3,0)*transform(1,1)*transform(0,3);
|
||||||
|
|
||||||
return det > 0;
|
return det > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +515,70 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderSubMeshImpl(const StdMeshInstance& mesh_instance, const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
StdProjectionMatrix ResolveAutoTextureMatrix(const StdSubMeshInstance& instance, const StdMeshMaterialTechnique& technique, unsigned int passIndex, unsigned int texUnitIndex)
|
||||||
|
{
|
||||||
|
assert(passIndex < technique.Passes.size());
|
||||||
|
const StdMeshMaterialPass& pass = technique.Passes[passIndex];
|
||||||
|
|
||||||
|
assert(texUnitIndex < pass.TextureUnits.size());
|
||||||
|
const StdMeshMaterialTextureUnit& texunit = pass.TextureUnits[texUnitIndex];
|
||||||
|
|
||||||
|
StdProjectionMatrix matrix = StdProjectionMatrix::Identity();
|
||||||
|
const double Position = instance.GetTexturePosition(passIndex, texUnitIndex);
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < texunit.Transformations.size(); ++k)
|
||||||
|
{
|
||||||
|
const StdMeshMaterialTextureUnit::Transformation& trans = texunit.Transformations[k];
|
||||||
|
StdProjectionMatrix temp_matrix;
|
||||||
|
switch (trans.TransformType)
|
||||||
|
{
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_SCROLL:
|
||||||
|
Translate(matrix, trans.Scroll.X, trans.Scroll.Y, 0.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_SCROLL_ANIM:
|
||||||
|
Translate(matrix, trans.GetScrollX(Position), trans.GetScrollY(Position), 0.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_ROTATE:
|
||||||
|
Rotate(matrix, trans.Rotate.Angle, 0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_ROTATE_ANIM:
|
||||||
|
Rotate(matrix, trans.GetRotate(Position), 0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_SCALE:
|
||||||
|
Scale(matrix, trans.Scale.X, trans.Scale.Y, 1.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_TRANSFORM:
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
temp_matrix(i / 4, i % 4) = trans.Transform.M[i];
|
||||||
|
matrix *= temp_matrix;
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::T_WAVE_XFORM:
|
||||||
|
switch (trans.WaveXForm.XForm)
|
||||||
|
{
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_X:
|
||||||
|
Translate(matrix, trans.GetWaveXForm(Position), 0.0f, 0.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_Y:
|
||||||
|
Translate(matrix, 0.0f, trans.GetWaveXForm(Position), 0.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::XF_ROTATE:
|
||||||
|
Rotate(matrix, trans.GetWaveXForm(Position), 0.0f, 0.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::XF_SCALE_X:
|
||||||
|
Scale(matrix, trans.GetWaveXForm(Position), 1.0f, 1.0f);
|
||||||
|
break;
|
||||||
|
case StdMeshMaterialTextureUnit::Transformation::XF_SCALE_Y:
|
||||||
|
Scale(matrix, 1.0f, trans.GetWaveXForm(Position), 1.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderSubMeshImpl(const StdProjectionMatrix& projectionMatrix, const StdMeshMatrix& modelviewMatrix, const StdMeshInstance& mesh_instance, const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
||||||
{
|
{
|
||||||
const StdMeshMaterial& material = instance.GetMaterial();
|
const StdMeshMaterial& material = instance.GetMaterial();
|
||||||
assert(material.BestTechniqueIndex != -1);
|
assert(material.BestTechniqueIndex != -1);
|
||||||
|
@ -535,6 +620,9 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modelview matrix does not change between passes, so cache it here
|
||||||
|
const StdMeshMatrix normalMatrixTranspose = StdMeshMatrix::Inverse(modelviewMatrix);
|
||||||
|
|
||||||
// Render each pass
|
// Render each pass
|
||||||
for (unsigned int i = 0; i < technique.Passes.size(); ++i)
|
for (unsigned int i = 0; i < technique.Passes.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -602,11 +690,9 @@ namespace
|
||||||
glBlendFunc(OgreBlendTypeToGL(pass.SceneBlendFactors[0]), GL_ONE);
|
glBlendFunc(OgreBlendTypeToGL(pass.SceneBlendFactors[0]), GL_ONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
glMatrixMode(GL_TEXTURE);
|
|
||||||
|
|
||||||
assert(pass.Program.get() != NULL);
|
assert(pass.Program.get() != NULL);
|
||||||
|
|
||||||
// Upload all parameters to the shader (keep GL_TEXTURE matrix mode for this)
|
// Upload all parameters to the shader
|
||||||
int ssc = 0;
|
int ssc = 0;
|
||||||
if(dwBlitMode & C4GFXBLIT_MOD2) ssc |= C4SSC_MOD2;
|
if(dwBlitMode & C4GFXBLIT_MOD2) ssc |= C4SSC_MOD2;
|
||||||
if(pFoW != NULL) ssc |= C4SSC_LIGHT;
|
if(pFoW != NULL) ssc |= C4SSC_LIGHT;
|
||||||
|
@ -615,6 +701,11 @@ namespace
|
||||||
C4ShaderCall call(shader);
|
C4ShaderCall call(shader);
|
||||||
call.Start();
|
call.Start();
|
||||||
|
|
||||||
|
// Upload projection, modelview and normal matrices
|
||||||
|
call.SetUniformMatrix4x4(C4SSU_ProjectionMatrix, projectionMatrix);
|
||||||
|
call.SetUniformMatrix4x4(C4SSU_ModelViewMatrix, modelviewMatrix);
|
||||||
|
call.SetUniformMatrix3x3Transpose(C4SSU_NormalMatrix, normalMatrixTranspose);
|
||||||
|
|
||||||
// Upload the current bone transformation matrixes (if there are any)
|
// Upload the current bone transformation matrixes (if there are any)
|
||||||
if (!bones.empty())
|
if (!bones.empty())
|
||||||
{
|
{
|
||||||
|
@ -641,6 +732,7 @@ namespace
|
||||||
}
|
}
|
||||||
#undef VERTEX_OFFSET
|
#undef VERTEX_OFFSET
|
||||||
|
|
||||||
|
// Bind textures
|
||||||
for (unsigned int j = 0; j < pass.TextureUnits.size(); ++j)
|
for (unsigned int j = 0; j < pass.TextureUnits.size(); ++j)
|
||||||
{
|
{
|
||||||
const StdMeshMaterialTextureUnit& texunit = pass.TextureUnits[j];
|
const StdMeshMaterialTextureUnit& texunit = pass.TextureUnits[j];
|
||||||
|
@ -649,66 +741,17 @@ namespace
|
||||||
call.AllocTexUnit(-1);
|
call.AllocTexUnit(-1);
|
||||||
const unsigned int Phase = instance.GetTexturePhase(i, j);
|
const unsigned int Phase = instance.GetTexturePhase(i, j);
|
||||||
glBindTexture(GL_TEXTURE_2D, texunit.GetTexture(Phase).texName);
|
glBindTexture(GL_TEXTURE_2D, texunit.GetTexture(Phase).texName);
|
||||||
|
|
||||||
// Setup texture coordinate transform
|
|
||||||
glLoadIdentity();
|
|
||||||
const double Position = instance.GetTexturePosition(i, j);
|
|
||||||
for (unsigned int k = 0; k < texunit.Transformations.size(); ++k)
|
|
||||||
{
|
|
||||||
const StdMeshMaterialTextureUnit::Transformation& trans = texunit.Transformations[k];
|
|
||||||
switch (trans.TransformType)
|
|
||||||
{
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_SCROLL:
|
|
||||||
glTranslatef(trans.Scroll.X, trans.Scroll.Y, 0.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_SCROLL_ANIM:
|
|
||||||
glTranslatef(trans.GetScrollX(Position), trans.GetScrollY(Position), 0.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_ROTATE:
|
|
||||||
glRotatef(trans.Rotate.Angle, 0.0f, 0.0f, 1.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_ROTATE_ANIM:
|
|
||||||
glRotatef(trans.GetRotate(Position), 0.0f, 0.0f, 1.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_SCALE:
|
|
||||||
glScalef(trans.Scale.X, trans.Scale.Y, 1.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_TRANSFORM:
|
|
||||||
glMultMatrixf(trans.Transform.M);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::T_WAVE_XFORM:
|
|
||||||
switch (trans.WaveXForm.XForm)
|
|
||||||
{
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_X:
|
|
||||||
glTranslatef(trans.GetWaveXForm(Position), 0.0f, 0.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_Y:
|
|
||||||
glTranslatef(0.0f, trans.GetWaveXForm(Position), 0.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::XF_ROTATE:
|
|
||||||
glRotatef(trans.GetWaveXForm(Position), 0.0f, 0.0f, 1.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::XF_SCALE_X:
|
|
||||||
glScalef(trans.GetWaveXForm(Position), 1.0f, 1.0f);
|
|
||||||
break;
|
|
||||||
case StdMeshMaterialTextureUnit::Transformation::XF_SCALE_Y:
|
|
||||||
glScalef(1.0f, trans.GetWaveXForm(Position), 1.0f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set uniforms and instance parameters
|
// Set uniforms and instance parameters
|
||||||
SetStandardUniforms(call, dwModClr, dwPlayerColor, dwBlitMode, pass.CullHardware != StdMeshMaterialPass::CH_None, pFoW, clipRect, outRect);
|
SetStandardUniforms(call, dwModClr, dwPlayerColor, dwBlitMode, pass.CullHardware != StdMeshMaterialPass::CH_None, pFoW, clipRect, outRect);
|
||||||
for(unsigned int i = 0; i < pass.Program->Parameters.size(); ++i)
|
for(unsigned int j = 0; j < pass.Program->Parameters.size(); ++j)
|
||||||
{
|
{
|
||||||
const int uniform = pass.Program->Parameters[i].UniformIndex;
|
const int uniform = pass.Program->Parameters[j].UniformIndex;
|
||||||
if(!shader->HaveUniform(uniform)) continue; // optimized out
|
if(!shader->HaveUniform(uniform)) continue; // optimized out
|
||||||
|
|
||||||
const StdMeshMaterialShaderParameter* parameter = pass.Program->Parameters[i].Parameter;
|
const StdMeshMaterialShaderParameter* parameter = pass.Program->Parameters[j].Parameter;
|
||||||
|
|
||||||
StdMeshMaterialShaderParameter auto_resolved;
|
StdMeshMaterialShaderParameter auto_resolved;
|
||||||
if(parameter->GetType() == StdMeshMaterialShaderParameter::AUTO)
|
if(parameter->GetType() == StdMeshMaterialShaderParameter::AUTO)
|
||||||
|
@ -720,6 +763,9 @@ namespace
|
||||||
|
|
||||||
switch(parameter->GetType())
|
switch(parameter->GetType())
|
||||||
{
|
{
|
||||||
|
case StdMeshMaterialShaderParameter::AUTO_TEXTURE_MATRIX:
|
||||||
|
call.SetUniformMatrix4x4(uniform, ResolveAutoTextureMatrix(instance, technique, i, parameter->GetInt()));
|
||||||
|
break;
|
||||||
case StdMeshMaterialShaderParameter::INT:
|
case StdMeshMaterialShaderParameter::INT:
|
||||||
call.SetUniform1i(uniform, parameter->GetInt());
|
call.SetUniform1i(uniform, parameter->GetInt());
|
||||||
break;
|
break;
|
||||||
|
@ -744,7 +790,6 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
size_t vertex_count = 3 * instance.GetNumFaces();
|
size_t vertex_count = 3 * instance.GetNumFaces();
|
||||||
glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, instance.GetFaces());
|
glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, instance.GetFaces());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
@ -760,21 +805,12 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity); // Needed by RenderAttachedMesh
|
void RenderMeshImpl(const StdProjectionMatrix& projectionMatrix, const StdMeshMatrix& modelviewMatrix, StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity); // Needed by RenderAttachedMesh
|
||||||
|
|
||||||
void RenderAttachedMesh(StdMeshInstance::AttachedMesh* attach, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
void RenderAttachedMesh(const StdProjectionMatrix& projectionMatrix, const StdMeshMatrix& modelviewMatrix, StdMeshInstance::AttachedMesh* attach, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
||||||
{
|
{
|
||||||
const StdMeshMatrix& FinalTrans = attach->GetFinalTransformation();
|
const StdMeshMatrix& FinalTrans = attach->GetFinalTransformation();
|
||||||
|
|
||||||
// Convert matrix to column-major order, add fourth row
|
|
||||||
const float attach_trans_gl[16] =
|
|
||||||
{
|
|
||||||
FinalTrans(0,0), FinalTrans(1,0), FinalTrans(2,0), 0,
|
|
||||||
FinalTrans(0,1), FinalTrans(1,1), FinalTrans(2,1), 0,
|
|
||||||
FinalTrans(0,2), FinalTrans(1,2), FinalTrans(2,2), 0,
|
|
||||||
FinalTrans(0,3), FinalTrans(1,3), FinalTrans(2,3), 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// Take the player color from the C4Object, if the attached object is not a definition
|
// Take the player color from the C4Object, if the attached object is not a definition
|
||||||
// This is a bit unfortunate because it requires access to C4Object which is otherwise
|
// This is a bit unfortunate because it requires access to C4Object which is otherwise
|
||||||
// avoided in this code. It could be replaced by virtual function calls to StdMeshDenumerator
|
// avoided in this code. It could be replaced by virtual function calls to StdMeshDenumerator
|
||||||
|
@ -787,13 +823,11 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Take attach transform's parity into account
|
// TODO: Take attach transform's parity into account
|
||||||
glPushMatrix();
|
StdMeshMatrix newModelviewMatrix = modelviewMatrix * FinalTrans;
|
||||||
glMultMatrixf(attach_trans_gl);
|
RenderMeshImpl(projectionMatrix, newModelviewMatrix, *attach->Child, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
||||||
RenderMeshImpl(*attach->Child, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
void RenderMeshImpl(const StdProjectionMatrix& projectionMatrix, const StdMeshMatrix& modelviewMatrix, StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, const C4FoWRegion* pFoW, const C4Rect& clipRect, const C4Rect& outRect, bool parity)
|
||||||
{
|
{
|
||||||
const StdMesh& mesh = instance.GetMesh();
|
const StdMesh& mesh = instance.GetMesh();
|
||||||
|
|
||||||
|
@ -801,7 +835,7 @@ namespace
|
||||||
StdMeshInstance::AttachedMeshIter attach_iter = instance.AttachedMeshesBegin();
|
StdMeshInstance::AttachedMeshIter attach_iter = instance.AttachedMeshesBegin();
|
||||||
|
|
||||||
for (; attach_iter != instance.AttachedMeshesEnd() && ((*attach_iter)->GetFlags() & StdMeshInstance::AM_DrawBefore); ++attach_iter)
|
for (; attach_iter != instance.AttachedMeshesEnd() && ((*attach_iter)->GetFlags() & StdMeshInstance::AM_DrawBefore); ++attach_iter)
|
||||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
RenderAttachedMesh(projectionMatrix, modelviewMatrix, *attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
||||||
|
|
||||||
GLint modes[2];
|
GLint modes[2];
|
||||||
// Check if we should draw in wireframe or normal mode
|
// Check if we should draw in wireframe or normal mode
|
||||||
|
@ -814,7 +848,7 @@ namespace
|
||||||
|
|
||||||
// Render each submesh
|
// Render each submesh
|
||||||
for (unsigned int i = 0; i < mesh.GetNumSubMeshes(); ++i)
|
for (unsigned int i = 0; i < mesh.GetNumSubMeshes(); ++i)
|
||||||
RenderSubMeshImpl(instance, instance.GetSubMeshOrdered(i), dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
RenderSubMeshImpl(projectionMatrix, modelviewMatrix, instance, instance.GetSubMeshOrdered(i), dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
||||||
|
|
||||||
// reset old mode to prevent rendering errors
|
// reset old mode to prevent rendering errors
|
||||||
if(dwBlitMode & C4GFXBLIT_WIREFRAME)
|
if(dwBlitMode & C4GFXBLIT_WIREFRAME)
|
||||||
|
@ -825,7 +859,7 @@ namespace
|
||||||
|
|
||||||
// Render non-AM_DrawBefore attached meshes
|
// Render non-AM_DrawBefore attached meshes
|
||||||
for (; attach_iter != instance.AttachedMeshesEnd(); ++attach_iter)
|
for (; attach_iter != instance.AttachedMeshesEnd(); ++attach_iter)
|
||||||
RenderAttachedMesh(*attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
RenderAttachedMesh(projectionMatrix, modelviewMatrix, *attach_iter, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,23 +901,21 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
||||||
//int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
|
//int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
|
||||||
//glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
|
//glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Set up projection matrix first. We do transform and Zoom with the
|
|
||||||
// projection matrix, so that lighting is applied to the untransformed/unzoomed
|
|
||||||
// mesh.
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPushMatrix();
|
|
||||||
|
|
||||||
// Mesh extents
|
// Mesh extents
|
||||||
const float b = fabs(v2.x - v1.x)/2.0f;
|
const float b = fabs(v2.x - v1.x)/2.0f;
|
||||||
const float h = fabs(v2.y - v1.y)/2.0f;
|
const float h = fabs(v2.y - v1.y)/2.0f;
|
||||||
const float l = fabs(v2.z - v1.z)/2.0f;
|
const float l = fabs(v2.z - v1.z)/2.0f;
|
||||||
|
|
||||||
|
// Set up projection matrix first. We do transform and Zoom with the
|
||||||
|
// projection matrix, so that lighting is applied to the untransformed/unzoomed
|
||||||
|
// mesh.
|
||||||
|
StdProjectionMatrix projectionMatrix;
|
||||||
if (!fUsePerspective)
|
if (!fUsePerspective)
|
||||||
{
|
{
|
||||||
// Orthographic projection. The orthographic projection matrix
|
// Load the orthographic projection
|
||||||
// is already loaded in the GL matrix stack.
|
projectionMatrix = ProjectionMatrix;
|
||||||
|
|
||||||
if (!ApplyZoomAndTransform(ZoomX, ZoomY, Zoom, pTransform))
|
if (!ApplyZoomAndTransform(ZoomX, ZoomY, Zoom, pTransform, projectionMatrix))
|
||||||
parity = !parity;
|
parity = !parity;
|
||||||
|
|
||||||
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
|
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
|
||||||
|
@ -913,24 +945,22 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
||||||
// there are attached meshes.
|
// there are attached meshes.
|
||||||
const float scz = 1.0/(mesh.GetBoundingRadius());
|
const float scz = 1.0/(mesh.GetBoundingRadius());
|
||||||
|
|
||||||
glTranslatef(dx, dy, 0.0f);
|
Translate(projectionMatrix, dx, dy, 0.0f);
|
||||||
glScalef(1.0f, 1.0f, scz);
|
Scale(projectionMatrix, 1.0f, 1.0f, scz);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Perspective projection. We need current viewport size.
|
// Perspective projection. This code transforms the projected
|
||||||
const int iWdt=std::min(iClipX2, RenderTarget->Wdt-1)-iClipX1+1;
|
// 3D model into the target area.
|
||||||
const int iHgt=std::min(iClipY2, RenderTarget->Hgt-1)-iClipY1+1;
|
const C4Rect clipRect = GetClipRect();
|
||||||
|
projectionMatrix = StdProjectionMatrix::Identity();
|
||||||
// Get away with orthographic projection matrix currently loaded
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Back to GL device coordinates
|
// Back to GL device coordinates
|
||||||
glTranslatef(-1.0f, 1.0f, 0.0f);
|
Translate(projectionMatrix, -1.0f, 1.0f, 0.0f);
|
||||||
glScalef(2.0f/iWdt, -2.0f/iHgt, 1.0f);
|
Scale(projectionMatrix, 2.0f/clipRect.Wdt, -2.0f/clipRect.Hgt, 1.0f);
|
||||||
|
|
||||||
glTranslatef(-iClipX1, -iClipY1, 0.0f);
|
Translate(projectionMatrix, -clipRect.x, -clipRect.y, 0.0f);
|
||||||
if (!ApplyZoomAndTransform(ZoomX, ZoomY, Zoom, pTransform))
|
if (!ApplyZoomAndTransform(ZoomX, ZoomY, Zoom, pTransform, projectionMatrix))
|
||||||
parity = !parity;
|
parity = !parity;
|
||||||
|
|
||||||
// Move to target location and compensate for 1.0f aspect
|
// Move to target location and compensate for 1.0f aspect
|
||||||
|
@ -946,87 +976,66 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
||||||
ttwdt = thgt;
|
ttwdt = thgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
glTranslatef(ttx, tty, 0.0f);
|
Translate(projectionMatrix, ttx, tty, 0.0f);
|
||||||
glScalef(((float)ttwdt)/iWdt, ((float)tthgt)/iHgt, 1.0f);
|
Scale(projectionMatrix, ((float)ttwdt)/clipRect.Wdt, ((float)tthgt)/clipRect.Hgt, 1.0f);
|
||||||
|
|
||||||
// Return to Clonk coordinate frame
|
// Return to Clonk coordinate frame
|
||||||
glScalef(iWdt/2.0, -iHgt/2.0, 1.0f);
|
Scale(projectionMatrix, clipRect.Wdt/2.0, -clipRect.Hgt/2.0, 1.0f);
|
||||||
glTranslatef(1.0f, -1.0f, 0.0f);
|
Translate(projectionMatrix, 1.0f, -1.0f, 0.0f);
|
||||||
|
|
||||||
// Fix for the case when we have a non-square target
|
// Fix for the case when we have different aspect ratios
|
||||||
const float ta = twdt / thgt;
|
const float ta = twdt / thgt;
|
||||||
const float ma = b / h;
|
const float ma = b / h;
|
||||||
if(ta <= 1 && ta/ma <= 1)
|
if(ta <= 1 && ta/ma <= 1)
|
||||||
glScalef(std::max(ta, ta/ma), std::max(ta, ta/ma), 1.0f);
|
Scale(projectionMatrix, std::max(ta, ta/ma), std::max(ta, ta/ma), 1.0f);
|
||||||
else if(ta >= 1 && ta/ma >= 1)
|
else if(ta >= 1 && ta/ma >= 1)
|
||||||
glScalef(std::max(1.0f/ta, ma/ta), std::max(1.0f/ta, ma/ta), 1.0f);
|
Scale(projectionMatrix, std::max(1.0f/ta, ma/ta), std::max(1.0f/ta, ma/ta), 1.0f);
|
||||||
|
|
||||||
// Apply perspective projection. After this, x and y range from
|
// Apply perspective projection. After this, x and y range from
|
||||||
// -1 to 1, and this is mapped into tx/ty/twdt/thgt by the above code.
|
// -1 to 1, and this is mapped into tx/ty/twdt/thgt by the above code.
|
||||||
// Aspect is 1.0f which is accounted for above.
|
// Aspect is 1.0f which is changed above as well.
|
||||||
gluPerspective(FOV, 1.0f, 0.1f, 100.0f);
|
Perspective(projectionMatrix, 1.0f/TAN_FOV, 1.0f, 0.1f, 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now set up modelview matrix
|
// Now set up the modelview matrix
|
||||||
glMatrixMode(GL_MODELVIEW);
|
StdMeshMatrix modelviewMatrix;
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
if (fUsePerspective)
|
if (fUsePerspective)
|
||||||
{
|
{
|
||||||
// Setup camera position so that the mesh with uniform transformation
|
// Setup camera position so that the mesh with uniform transformation
|
||||||
// fits well into a square target (without distortion).
|
// fits well into a square target (without distortion).
|
||||||
const float EyeR = l + std::max(b/TAN_FOV, h/TAN_FOV);
|
const float EyeR = l + std::max(b/TAN_FOV, h/TAN_FOV);
|
||||||
const float EyeX = MeshCenter.x;
|
const StdMeshVector Eye = StdMeshVector::Translate(MeshCenter.x, MeshCenter.y, MeshCenter.z + EyeR);
|
||||||
const float EyeY = MeshCenter.y;
|
|
||||||
const float EyeZ = MeshCenter.z + EyeR;
|
|
||||||
|
|
||||||
// Up vector is unit vector in theta direction
|
// Up vector is unit vector in theta direction
|
||||||
const float UpX = 0;//-sinEyePhi * sinEyeTheta;
|
const StdMeshVector Up = StdMeshVector::Translate(0.0f, -1.0f, 0.0f);
|
||||||
const float UpY = -1;//-cosEyeTheta;
|
|
||||||
const float UpZ = 0;//-cosEyePhi * sinEyeTheta;
|
|
||||||
|
|
||||||
// Fix X axis (???)
|
// Fix X axis (???)
|
||||||
glScalef(-1.0f, 1.0f, 1.0f);
|
modelviewMatrix = StdMeshMatrix::Scale(-1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
// center on mesh's bounding box, so that the mesh is really in the center of the viewport
|
// center on mesh's bounding box, so that the mesh is really in the center of the viewport
|
||||||
gluLookAt(EyeX, EyeY, EyeZ, MeshCenter.x, MeshCenter.y, MeshCenter.z, UpX, UpY, UpZ);
|
modelviewMatrix *= StdMeshMatrix::LookAt(Eye, MeshCenter, Up);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modelviewMatrix = StdMeshMatrix::Identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply mesh transformation matrix
|
// Apply mesh transformation matrix
|
||||||
if (MeshTransform)
|
if (MeshTransform)
|
||||||
{
|
{
|
||||||
// Convert to column-major order
|
|
||||||
const float Matrix[16] =
|
|
||||||
{
|
|
||||||
(*MeshTransform)(0,0), (*MeshTransform)(1,0), (*MeshTransform)(2,0), 0,
|
|
||||||
(*MeshTransform)(0,1), (*MeshTransform)(1,1), (*MeshTransform)(2,1), 0,
|
|
||||||
(*MeshTransform)(0,2), (*MeshTransform)(1,2), (*MeshTransform)(2,2), 0,
|
|
||||||
(*MeshTransform)(0,3), (*MeshTransform)(1,3), (*MeshTransform)(2,3), 1
|
|
||||||
};
|
|
||||||
|
|
||||||
const float det = MeshTransform->Determinant();
|
const float det = MeshTransform->Determinant();
|
||||||
if (det < 0) parity = !parity;
|
if (det < 0) parity = !parity;
|
||||||
|
|
||||||
// Renormalize if transformation resizes the mesh
|
|
||||||
// for lighting to be correct.
|
|
||||||
// TODO: Also needs to check for orthonormality to be correct
|
|
||||||
if (det != 1 && det != -1)
|
|
||||||
glEnable(GL_NORMALIZE);
|
|
||||||
|
|
||||||
// Apply MeshTransformation (in the Mesh's coordinate system)
|
// Apply MeshTransformation (in the Mesh's coordinate system)
|
||||||
glMultMatrixf(Matrix);
|
modelviewMatrix *= *MeshTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff;
|
DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff;
|
||||||
|
|
||||||
const C4Rect clipRect = GetClipRect();
|
const C4Rect clipRect = GetClipRect();
|
||||||
const C4Rect outRect = GetOutRect();
|
const C4Rect outRect = GetOutRect();
|
||||||
RenderMeshImpl(instance, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
RenderMeshImpl(projectionMatrix, modelviewMatrix, instance, dwModClr, dwBlitMode, dwPlayerColor, pFoW, clipRect, outRect, parity);
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0); // switch back to default
|
glActiveTexture(GL_TEXTURE0); // switch back to default
|
||||||
glClientActiveTexture(GL_TEXTURE0); // switch back to default
|
glClientActiveTexture(GL_TEXTURE0); // switch back to default
|
||||||
|
@ -1036,7 +1045,6 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
||||||
glDisableClientState(GL_NORMAL_ARRAY);
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
glDisable(GL_NORMALIZE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
|
|
|
@ -274,7 +274,7 @@ public:
|
||||||
{
|
{
|
||||||
if (pShader->HaveUniform(iUniform))
|
if (pShader->HaveUniform(iUniform))
|
||||||
{
|
{
|
||||||
const float mat[16] = { matrix(0, 0), matrix(1, 0), matrix(2, 0), 0.0f, matrix(0, 1), matrix(1, 1), matrix(1, 2), 0.0f, matrix(2, 0), matrix(2, 1), matrix(2, 2), 0.0f, matrix(0, 3), matrix(1, 3), matrix(2, 3), 1.0f };
|
const float mat[16] = { matrix(0, 0), matrix(1, 0), matrix(2, 0), 0.0f, matrix(0, 1), matrix(1, 1), matrix(2, 1), 0.0f, matrix(0, 2), matrix(1, 2), matrix(2, 2), 0.0f, matrix(0, 3), matrix(1, 3), matrix(2, 3), 1.0f };
|
||||||
glUniformMatrix4fvARB(pShader->GetUniform(iUniform), 1, GL_FALSE, mat);
|
glUniformMatrix4fvARB(pShader->GetUniform(iUniform), 1, GL_FALSE, mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -693,6 +693,7 @@ void StdMeshMaterialShaderParameter::CopyShallow(const StdMeshMaterialShaderPara
|
||||||
case AUTO:
|
case AUTO:
|
||||||
a = other.a;
|
a = other.a;
|
||||||
break;
|
break;
|
||||||
|
case AUTO_TEXTURE_MATRIX:
|
||||||
case INT:
|
case INT:
|
||||||
i = other.i;
|
i = other.i;
|
||||||
break;
|
break;
|
||||||
|
@ -864,9 +865,9 @@ bool StdMeshMaterialProgram::CompileShader(StdMeshMaterialLoader& loader, C4Shad
|
||||||
std::vector<const char*> uniformNames;
|
std::vector<const char*> uniformNames;
|
||||||
#ifndef USE_CONSOLE
|
#ifndef USE_CONSOLE
|
||||||
uniformNames.resize(C4SSU_Count + ParameterNames.size() + 1);
|
uniformNames.resize(C4SSU_Count + ParameterNames.size() + 1);
|
||||||
uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix"; // unused YET
|
uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix";
|
||||||
uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix"; // unused YET
|
uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix";
|
||||||
uniformNames[C4SSU_NormalMatrix] = "normalMatrix"; // unused YET
|
uniformNames[C4SSU_NormalMatrix] = "normalMatrix";
|
||||||
uniformNames[C4SSU_ClrMod] = "clrMod";
|
uniformNames[C4SSU_ClrMod] = "clrMod";
|
||||||
uniformNames[C4SSU_Gamma] = "gamma";
|
uniformNames[C4SSU_Gamma] = "gamma";
|
||||||
uniformNames[C4SSU_BaseTex] = "baseTex"; // unused
|
uniformNames[C4SSU_BaseTex] = "baseTex"; // unused
|
||||||
|
|
|
@ -47,6 +47,7 @@ class StdMeshMaterialShaderParameter
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
||||||
AUTO,
|
AUTO,
|
||||||
|
AUTO_TEXTURE_MATRIX, // Texture matrix for the i-th texture
|
||||||
INT,
|
INT,
|
||||||
FLOAT,
|
FLOAT,
|
||||||
FLOAT2,
|
FLOAT2,
|
||||||
|
@ -74,14 +75,14 @@ public:
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
Auto GetAuto() const { assert(type == AUTO); return a; }
|
Auto GetAuto() const { assert(type == AUTO); return a; }
|
||||||
int GetInt() const { assert(type == INT); return i; }
|
int GetInt() const { assert(type == INT || type == AUTO_TEXTURE_MATRIX); return i; }
|
||||||
float GetFloat() const { assert(type == FLOAT); return f[0]; }
|
float GetFloat() const { assert(type == FLOAT); return f[0]; }
|
||||||
const float* GetFloatv() const { assert(type == FLOAT2 || type == FLOAT3 || type == FLOAT4); return f; }
|
const float* GetFloatv() const { assert(type == FLOAT2 || type == FLOAT3 || type == FLOAT4); return f; }
|
||||||
const float* GetMatrix() const { assert(type == MATRIX_4X4); return matrix; }
|
const float* GetMatrix() const { assert(type == MATRIX_4X4); return matrix; }
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
Auto& GetAuto() { assert(type == AUTO); return a; }
|
Auto& GetAuto() { assert(type == AUTO); return a; }
|
||||||
int& GetInt() { assert(type == INT); return i; }
|
int& GetInt() { assert(type == INT || type == AUTO_TEXTURE_MATRIX); return i; }
|
||||||
float& GetFloat() { assert(type == FLOAT); return f[0]; }
|
float& GetFloat() { assert(type == FLOAT); return f[0]; }
|
||||||
float* GetFloatv() { assert(type == FLOAT2 || type == FLOAT3 || type == FLOAT4); return f; }
|
float* GetFloatv() { assert(type == FLOAT2 || type == FLOAT3 || type == FLOAT4); return f; }
|
||||||
float* GetMatrix() { assert(type == MATRIX_4X4); return matrix; }
|
float* GetMatrix() { assert(type == MATRIX_4X4); return matrix; }
|
||||||
|
|
|
@ -59,6 +59,12 @@ StdMeshVector StdMeshVector::Cross(const StdMeshVector& lhs, const StdMeshVector
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StdMeshVector::Normalize()
|
||||||
|
{
|
||||||
|
const float len = sqrt(x*x + y*y + z*z);
|
||||||
|
x /= len; y /= len; z /= len;
|
||||||
|
}
|
||||||
|
|
||||||
StdMeshQuaternion StdMeshQuaternion::Zero()
|
StdMeshQuaternion StdMeshQuaternion::Zero()
|
||||||
{
|
{
|
||||||
StdMeshQuaternion q;
|
StdMeshQuaternion q;
|
||||||
|
@ -337,6 +343,24 @@ StdMeshMatrix StdMeshMatrix::TransformInverse(const StdMeshTransformation& trans
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StdMeshMatrix StdMeshMatrix::LookAt(const StdMeshVector& eye, const StdMeshVector& center, const StdMeshVector& up)
|
||||||
|
{
|
||||||
|
// See http://stackoverflow.com/questions/349050/calculating-a-lookat-matrix
|
||||||
|
StdMeshVector z = eye - center;
|
||||||
|
z.Normalize();
|
||||||
|
|
||||||
|
StdMeshVector x = StdMeshVector::Cross(up, z);
|
||||||
|
x.Normalize();
|
||||||
|
|
||||||
|
StdMeshVector y = StdMeshVector::Cross(z, x);
|
||||||
|
|
||||||
|
StdMeshMatrix m;
|
||||||
|
m.a[0][0] = x.x; m.a[0][1] = x.y; m.a[0][2] = x.z; m.a[0][3] = -x.x*eye.x - x.y*eye.y - x.z*eye.z;
|
||||||
|
m.a[1][0] = y.x; m.a[1][1] = y.y; m.a[1][2] = y.z; m.a[1][3] = -y.x*eye.x - y.y*eye.y - y.z*eye.z;
|
||||||
|
m.a[2][0] = z.x; m.a[2][1] = z.y; m.a[2][2] = z.z; m.a[2][3] = -z.x*eye.x - z.y*eye.y - z.z*eye.z;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
float StdMeshMatrix::Determinant() const
|
float StdMeshMatrix::Determinant() const
|
||||||
{
|
{
|
||||||
return a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1]
|
return a[0][0]*a[1][1]*a[2][2] + a[0][1]*a[1][2]*a[2][0] + a[0][2]*a[1][0]*a[2][1]
|
||||||
|
@ -363,6 +387,33 @@ StdProjectionMatrix StdProjectionMatrix::Translate(float dx, float dy, float dz)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StdProjectionMatrix StdProjectionMatrix::Scale(float sx, float sy, float sz)
|
||||||
|
{
|
||||||
|
StdProjectionMatrix m;
|
||||||
|
m.a[0][0] = sx; m.a[0][1] = 0.0f; m.a[0][2] = 0.0f; m.a[0][3] = 0.0f;
|
||||||
|
m.a[1][0] = 0.0f; m.a[1][1] = sy; m.a[1][2] = 0.0f; m.a[1][3] = 0.0f;
|
||||||
|
m.a[2][0] = 0.0f; m.a[2][1] = 0.0f; m.a[2][2] = sz; m.a[2][3] = 0.0f;
|
||||||
|
m.a[3][0] = 0.0f; m.a[3][1] = 0.0f; m.a[3][2] = 0.0f; m.a[3][3] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdProjectionMatrix StdProjectionMatrix::Rotate(float angle, float rx, float ry, float rz)
|
||||||
|
{
|
||||||
|
StdProjectionMatrix m;
|
||||||
|
|
||||||
|
// We do normalize the rx,ry,rz vector here: This is only required for
|
||||||
|
// precalculations anyway, thus not time-critical.
|
||||||
|
float abs = sqrt(rx*rx+ry*ry+rz*rz);
|
||||||
|
rx/=abs; ry/=abs; rz/=abs;
|
||||||
|
float c = cos(angle), s = sin(angle);
|
||||||
|
|
||||||
|
m.a[0][0] = rx*rx*(1-c)+c; m.a[0][1] = rx*ry*(1-c)-rz*s; m.a[0][2] = rx*rz*(1-c)+ry*s; m.a[0][3] = 0.0f;
|
||||||
|
m.a[1][0] = ry*rx*(1-c)+rz*s; m.a[1][1] = ry*ry*(1-c)+c; m.a[1][2] = ry*rz*(1-c)-rx*s; m.a[1][3] = 0.0f;
|
||||||
|
m.a[2][0] = rz*rx*(1-c)-ry*s; m.a[2][1] = ry*rz*(1-c)+rx*s; m.a[2][2] = rz*rz*(1-c)+c; m.a[2][3] = 0.0f;
|
||||||
|
m.a[3][0] = 0.0f; m.a[3][1] = 0.0f; m.a[3][2] = 0.0f; m.a[3][3] = 1.0f;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
StdMeshMatrix StdProjectionMatrix::Upper3x4(const StdProjectionMatrix& matrix)
|
StdMeshMatrix StdProjectionMatrix::Upper3x4(const StdProjectionMatrix& matrix)
|
||||||
{
|
{
|
||||||
StdMeshMatrix m;
|
StdMeshMatrix m;
|
||||||
|
@ -611,6 +662,21 @@ StdMeshVector operator+(const StdMeshVector& lhs, const StdMeshVector& rhs)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StdMeshVector& operator-=(StdMeshVector& lhs, const StdMeshVector& rhs)
|
||||||
|
{
|
||||||
|
lhs.x -= rhs.x;
|
||||||
|
lhs.y -= rhs.y;
|
||||||
|
lhs.z -= rhs.z;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
StdMeshVector operator-(const StdMeshVector& lhs, const StdMeshVector& rhs)
|
||||||
|
{
|
||||||
|
StdMeshVector v(lhs);
|
||||||
|
v -= rhs;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs)
|
StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs)
|
||||||
{
|
{
|
||||||
StdMeshVector v;
|
StdMeshVector v;
|
||||||
|
|
|
@ -27,6 +27,8 @@ struct StdMeshVector
|
||||||
static StdMeshVector UnitScale();
|
static StdMeshVector UnitScale();
|
||||||
static StdMeshVector Translate(float dx, float dy, float dz);
|
static StdMeshVector Translate(float dx, float dy, float dz);
|
||||||
static StdMeshVector Cross(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
static StdMeshVector Cross(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
|
|
||||||
|
void Normalize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +100,7 @@ public:
|
||||||
static StdMeshMatrix Rotate(float angle, float rx, float ry, float rz);
|
static StdMeshMatrix Rotate(float angle, float rx, float ry, float rz);
|
||||||
static StdMeshMatrix Transform(const StdMeshTransformation& transform);
|
static StdMeshMatrix Transform(const StdMeshTransformation& transform);
|
||||||
static StdMeshMatrix TransformInverse(const StdMeshTransformation& transform);
|
static StdMeshMatrix TransformInverse(const StdMeshTransformation& transform);
|
||||||
|
static StdMeshMatrix LookAt(const StdMeshVector& eye, const StdMeshVector& center, const StdMeshVector& up);
|
||||||
|
|
||||||
float& operator()(int i, int j) { return a[i][j]; }
|
float& operator()(int i, int j) { return a[i][j]; }
|
||||||
float operator()(int i, int j) const { return a[i][j]; }
|
float operator()(int i, int j) const { return a[i][j]; }
|
||||||
|
@ -121,6 +124,8 @@ public:
|
||||||
|
|
||||||
static StdProjectionMatrix Identity();
|
static StdProjectionMatrix Identity();
|
||||||
static StdProjectionMatrix Translate(float dx, float dy, float dz);
|
static StdProjectionMatrix Translate(float dx, float dy, float dz);
|
||||||
|
static StdProjectionMatrix Scale(float sx, float sy, float sz);
|
||||||
|
static StdProjectionMatrix Rotate(float angle, float rx, float ry, float rz);
|
||||||
static StdMeshMatrix Upper3x4(const StdProjectionMatrix& matrix);
|
static StdMeshMatrix Upper3x4(const StdProjectionMatrix& matrix);
|
||||||
|
|
||||||
float& operator()(int i, int j) { return a[i][j]; }
|
float& operator()(int i, int j) { return a[i][j]; }
|
||||||
|
@ -153,6 +158,8 @@ StdMeshTransformation operator*(const StdMeshTransformation& lhs, const StdMeshT
|
||||||
StdMeshVector operator-(const StdMeshVector& rhs);
|
StdMeshVector operator-(const StdMeshVector& rhs);
|
||||||
StdMeshVector& operator+=(StdMeshVector& lhs, const StdMeshVector& rhs);
|
StdMeshVector& operator+=(StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
StdMeshVector operator+(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
StdMeshVector operator+(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
|
StdMeshVector& operator-=(StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
|
StdMeshVector operator-(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs);
|
||||||
StdMeshVector& operator*=(StdMeshVector& lhs, float rhs);
|
StdMeshVector& operator*=(StdMeshVector& lhs, float rhs);
|
||||||
StdMeshVector operator*(const StdMeshVector& lhs, float rhs);
|
StdMeshVector operator*(const StdMeshVector& lhs, float rhs);
|
||||||
|
@ -194,4 +201,32 @@ void Scale(MatrixType& mat, float sx, float sy, float sz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiply in-place the given matrix with a rotation matrix to the right
|
||||||
|
template<typename MatrixType>
|
||||||
|
void Rotate(MatrixType& mat, float angle, float x, float y, float z)
|
||||||
|
{
|
||||||
|
mat *= MatrixType::Rotate(angle, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiply in-place the given matrix with a perspective projection matrix to the right
|
||||||
|
template<typename MatrixType>
|
||||||
|
void Perspective(MatrixType& mat, float cot_fovy2, float aspect, float nearVal, float farVal)
|
||||||
|
{
|
||||||
|
static_assert(MatrixType::NColumns >= 4, "Matrix must have at least 4 columns");
|
||||||
|
|
||||||
|
const float fa = cot_fovy2 / aspect;
|
||||||
|
const float fb = cot_fovy2;
|
||||||
|
const float z1 = (nearVal + farVal) / (nearVal - farVal);
|
||||||
|
const float z2 = 2 * nearVal * farVal / (nearVal - farVal);
|
||||||
|
|
||||||
|
for (int i = 0; i < MatrixType::NRows; ++i)
|
||||||
|
{
|
||||||
|
const float mat2 = mat(i, 2);
|
||||||
|
mat(i, 0) *= fa;
|
||||||
|
mat(i, 1) *= fb;
|
||||||
|
mat(i, 2) = mat2 * z1 - mat(i, 3);
|
||||||
|
mat(i, 3) = mat2 * z2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue