forked from Mirrors/openclonk
Add support for scene_blend in material scripts (#303)
parent
6729c0ca64
commit
e282de55f1
|
@ -6,6 +6,7 @@ material RopeBalloon
|
|||
pass
|
||||
{
|
||||
cull_hardware none
|
||||
scene_blend src_alpha one_minus_src_alpha
|
||||
|
||||
ambient 1.500000 1.500000 1.500000 1.000000
|
||||
diffuse 0.640000 0.640000 0.640000 1.000000
|
||||
|
|
|
@ -996,12 +996,7 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP
|
|||
if (dwClrModulation != 0xffffff) Application.DDraw->ActivateBlitModulation(dwClrModulation);
|
||||
|
||||
if (pMeshInstance)
|
||||
{
|
||||
if ( ((dwClrModulation >> 24) & 0xff) != 0xff)
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
else
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
||||
}
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation);
|
||||
}
|
||||
if (eMode == MODE_Rank)
|
||||
{
|
||||
|
@ -1174,12 +1169,7 @@ void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj)
|
|||
if (dwClrModulation != 0xffffff) Application.DDraw->ActivateBlitModulation(dwClrModulation);
|
||||
|
||||
if (pMeshInstance)
|
||||
{
|
||||
if ( ((dwClrModulation >> 24) & 0xff) != 0xff)
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
else
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
||||
}
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation);
|
||||
}
|
||||
// draw at given rect
|
||||
if (!pMeshInstance)
|
||||
|
|
|
@ -251,8 +251,7 @@ bool C4Object::Init(C4PropList *pDef, C4Object *pCreator,
|
|||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
{
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -486,8 +485,7 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp)
|
|||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||
{
|
||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2847,12 +2845,11 @@ void C4Object::CompileFunc(StdCompiler *pComp)
|
|||
Action.PhaseDelay=iPhaseDelay;
|
||||
}*/
|
||||
|
||||
// Set Action animation by slot 0
|
||||
if (pMeshInstance)
|
||||
{
|
||||
// Set Action animation by slot 0
|
||||
Action.Animation = pMeshInstance->GetRootAnimationForSlot(0);
|
||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||
}
|
||||
|
||||
// if on fire but no effect is present (old-style savegames), re-incinerate
|
||||
|
|
|
@ -3421,12 +3421,7 @@ static bool FnSetClrModulation(C4AulObjectContext *cthr, Nillable<long> dwClr, l
|
|||
// set it
|
||||
cthr->Obj->ColorMod=clr;
|
||||
if (cthr->Obj->pMeshInstance)
|
||||
{
|
||||
if ( ((clr >> 24) & 0xff) != 0xff)
|
||||
cthr->Obj->pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
||||
else
|
||||
cthr->Obj->pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
||||
}
|
||||
cthr->Obj->pMeshInstance->SetFaceOrderingForClrModulation(clr);
|
||||
}
|
||||
// success
|
||||
return true;
|
||||
|
|
|
@ -40,6 +40,9 @@ CStdDDraw *lpDDraw=NULL;
|
|||
CStdPalette *lpDDrawPal=NULL;
|
||||
int iGfxEngine=-1;
|
||||
|
||||
// Transformation matrix to convert meshes from Ogre to Clonk coordinate system
|
||||
const StdMeshMatrix CStdDDraw::OgreToClonk = StdMeshMatrix::Scale(-1.0f, 1.0f, 1.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 1.0f, 0.0f, 0.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
inline void SetRect(RECT &rect, int left, int top, int right, int bottom)
|
||||
{
|
||||
rect.left=left; rect.top=top; rect.bottom=bottom; rect.right=right;
|
||||
|
@ -702,6 +705,10 @@ bool CStdDDraw::RenderMesh(StdMeshInstance &instance, SURFACE sfcTarget, float t
|
|||
if (!PrepareRendering(sfcTarget)) return false;
|
||||
// Update bone matrices and vertex data (note this also updates attach transforms and child transforms)
|
||||
instance.UpdateBoneTransforms();
|
||||
// Order faces according to MeshTransformation (note pTransform does not affect Z coordinate, so does not need to be taken into account for correct ordering)
|
||||
StdMeshMatrix mat = OgreToClonk;
|
||||
if(MeshTransform) mat = *MeshTransform * mat;
|
||||
instance.ReorderFaces(&mat);
|
||||
// Render mesh
|
||||
PerformMesh(instance, tx, ty, twdt, thgt, dwPlayerColor, pTransform);
|
||||
// success
|
||||
|
|
|
@ -210,6 +210,8 @@ struct ZoomData
|
|||
class CStdDDraw
|
||||
{
|
||||
public:
|
||||
static const StdMeshMatrix OgreToClonk;
|
||||
|
||||
CStdDDraw(): MaxTexSize(0), Saturation(255) { lpDDrawPal=&Pal; }
|
||||
virtual ~CStdDDraw() { lpDDraw=NULL; }
|
||||
public:
|
||||
|
|
|
@ -677,7 +677,25 @@ namespace
|
|||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Color);
|
||||
}
|
||||
|
||||
void RenderSubMeshImpl(const StdSubMeshInstance& instance, DWORD dwModClr, bool fMod2, DWORD dwPlayerColor, bool parity)
|
||||
inline GLenum OgreBlendTypeToGL(StdMeshMaterialPass::SceneBlendType blend)
|
||||
{
|
||||
switch(blend)
|
||||
{
|
||||
case StdMeshMaterialPass::SB_One: return GL_ONE;
|
||||
case StdMeshMaterialPass::SB_Zero: return GL_ZERO;
|
||||
case StdMeshMaterialPass::SB_DestColor: return GL_DST_COLOR;
|
||||
case StdMeshMaterialPass::SB_SrcColor: return GL_SRC_COLOR;
|
||||
case StdMeshMaterialPass::SB_OneMinusDestColor: return GL_ONE_MINUS_DST_COLOR;
|
||||
case StdMeshMaterialPass::SB_OneMinusSrcColor: return GL_ONE_MINUS_SRC_COLOR;
|
||||
case StdMeshMaterialPass::SB_DestAlpha: return GL_DST_ALPHA;
|
||||
case StdMeshMaterialPass::SB_SrcAlpha: return GL_SRC_ALPHA;
|
||||
case StdMeshMaterialPass::SB_OneMinusDestAlpha: return GL_ONE_MINUS_DST_ALPHA;
|
||||
case StdMeshMaterialPass::SB_OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA;
|
||||
default: assert(false); return GL_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSubMeshImpl(const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, bool parity)
|
||||
{
|
||||
const StdMeshMaterial& material = instance.GetMaterial();
|
||||
assert(material.BestTechniqueIndex != -1);
|
||||
|
@ -697,7 +715,7 @@ namespace
|
|||
// clrmodmap texture needs to be the last texture in that case... we should
|
||||
// change the index to maxtextures-1 instead of 3.
|
||||
|
||||
if(!fMod2 && dwModClr == 0xffffffff)
|
||||
if(!(dwBlitMode & C4GFXBLIT_MOD2) && dwModClr == 0xffffffff)
|
||||
{
|
||||
// Fastpath for the easy case
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, pass.Ambient);
|
||||
|
@ -719,7 +737,7 @@ namespace
|
|||
// TODO: We could also consider applying dwmod using an additional
|
||||
// texture unit, maybe we can even re-use the one which is reserved for
|
||||
// the clrmodmap texture anyway (+adapt the shader).
|
||||
if(!fMod2)
|
||||
if(!(dwBlitMode & C4GFXBLIT_MOD2))
|
||||
{
|
||||
Ambient[0] = pass.Ambient[0] * dwMod[0];
|
||||
Ambient[1] = pass.Ambient[1] * dwMod[1];
|
||||
|
@ -786,6 +804,16 @@ namespace
|
|||
break;
|
||||
}
|
||||
|
||||
if(!(dwBlitMode & C4GFXBLIT_ADDITIVE))
|
||||
{
|
||||
glBlendFunc(OgreBlendTypeToGL(pass.SceneBlendFactors[0]),
|
||||
OgreBlendTypeToGL(pass.SceneBlendFactors[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFunc(OgreBlendTypeToGL(pass.SceneBlendFactors[0]), GL_ONE);
|
||||
}
|
||||
|
||||
// TODO: Use vbo if available.
|
||||
// Note that we need to do this before we do glTexCoordPointer for the
|
||||
// texture units below, otherwise the texcoordpointer is reset by this
|
||||
|
@ -968,13 +996,13 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, bool fMod2, DWORD dwPlayerColor, bool parity)
|
||||
void RenderMeshImpl(StdMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, bool parity)
|
||||
{
|
||||
const StdMesh& mesh = instance.Mesh;
|
||||
|
||||
// Render each submesh
|
||||
for (unsigned int i = 0; i < mesh.GetNumSubMeshes(); ++i)
|
||||
RenderSubMeshImpl(instance.GetSubMesh(i), dwModClr, fMod2, dwPlayerColor, parity);
|
||||
RenderSubMeshImpl(instance.GetSubMesh(i), dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||
|
||||
#if 0
|
||||
// Draw attached bone
|
||||
|
@ -1015,7 +1043,7 @@ namespace
|
|||
// TODO: Take attach transform's parity into account
|
||||
glPushMatrix();
|
||||
glMultMatrixf(attach_trans_gl);
|
||||
RenderMeshImpl(*attach->Child, dwModClr, fMod2, dwPlayerColor, parity);
|
||||
RenderMeshImpl(*attach->Child, dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||
glPopMatrix();
|
||||
|
||||
#if 0
|
||||
|
@ -1068,29 +1096,25 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Generate matrix to convert the mesh from Ogre coordinate system to Clonk coordinate system.
|
||||
const StdMeshMatrix OgreToClonk = StdMeshMatrix::Scale(-1.0f, 1.0f, 1.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 1.0f, 0.0f, 0.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Convert to column-major order
|
||||
const float OgreToClonkGL[16] =
|
||||
{
|
||||
OgreToClonk(0,0), OgreToClonk(1,0), OgreToClonk(2,0), 0,
|
||||
OgreToClonk(0,1), OgreToClonk(1,1), OgreToClonk(2,1), 0,
|
||||
OgreToClonk(0,2), OgreToClonk(1,2), OgreToClonk(2,2), 0,
|
||||
OgreToClonk(0,3), OgreToClonk(1,3), OgreToClonk(2,3), 1
|
||||
};
|
||||
|
||||
const bool OgreToClonkParity = OgreToClonk.Determinant() > 0.0f;
|
||||
}
|
||||
|
||||
void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, CBltTransform* pTransform)
|
||||
{
|
||||
// Field of View for perspective projection, in degrees
|
||||
static const float FOV = 60.0f;
|
||||
static const float TAN_FOV = tan(FOV / 2.0f / 180.0f * M_PI);
|
||||
|
||||
// Convert OgreToClonk matrix to column-major order
|
||||
// TODO: This must be executed after CStdDDraw::OgreToClonk was
|
||||
// initialized - is this guaranteed at this position?
|
||||
static const float OgreToClonkGL[16] =
|
||||
{
|
||||
CStdDDraw::OgreToClonk(0,0), CStdDDraw::OgreToClonk(1,0), CStdDDraw::OgreToClonk(2,0), 0,
|
||||
CStdDDraw::OgreToClonk(0,1), CStdDDraw::OgreToClonk(1,1), CStdDDraw::OgreToClonk(2,1), 0,
|
||||
CStdDDraw::OgreToClonk(0,2), CStdDDraw::OgreToClonk(1,2), CStdDDraw::OgreToClonk(2,2), 0,
|
||||
CStdDDraw::OgreToClonk(0,3), CStdDDraw::OgreToClonk(1,3), CStdDDraw::OgreToClonk(2,3), 1
|
||||
};
|
||||
|
||||
static const bool OgreToClonkParity = CStdDDraw::OgreToClonk.Determinant() > 0.0f;
|
||||
|
||||
const StdMesh& mesh = instance.Mesh;
|
||||
|
||||
bool parity = OgreToClonkParity;
|
||||
|
@ -1112,8 +1136,12 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_BLEND); // TODO: Shouldn't this always be enabled? - blending does not work for meshes without this though.
|
||||
int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
|
||||
glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// TODO: We ignore the additive drawing flag for meshes but instead
|
||||
// set the blending mode of the corresponding material. I'm not sure
|
||||
// how the two could be combined.
|
||||
//int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
|
||||
//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
|
||||
|
@ -1301,7 +1329,7 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
ModulateClr(dwModClr, c);
|
||||
}
|
||||
|
||||
RenderMeshImpl(instance, dwModClr, !!(dwBlitMode & C4GFXBLIT_MOD2), dwPlayerColor, parity);
|
||||
RenderMeshImpl(instance, dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
|
|
@ -30,18 +30,15 @@ std::vector<StdMeshInstance::SerializableValueProvider::IDBase*>* StdMeshInstanc
|
|||
|
||||
namespace
|
||||
{
|
||||
// TODO: Avoid duplication with StdGL.cpp. This should not be here but possibly a parameter to ReorderFaces(),
|
||||
// which should then be called from StdDDraw::RenderMesh. That way it can also include MeshTransformation.
|
||||
const StdMeshMatrix OgreToClonk = StdMeshMatrix::Scale(-1.0f, 1.0f, 1.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 1.0f, 0.0f, 0.0f) * StdMeshMatrix::Rotate(float(M_PI)/2.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Helper to sort faces for FaceOrdering
|
||||
struct StdMeshInstanceFaceOrderingCmpPred
|
||||
{
|
||||
const StdMeshInstance& m_inst;
|
||||
const StdMeshVertex* m_vertices;
|
||||
const StdMeshMatrix& m_global_trans;
|
||||
|
||||
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& inst, unsigned int submesh):
|
||||
m_inst(inst), m_vertices(m_inst.GetSubMesh(submesh).GetVertices()) {}
|
||||
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& inst, unsigned int submesh, const StdMeshMatrix& global_trans):
|
||||
m_inst(inst), m_vertices(m_inst.GetSubMesh(submesh).GetVertices()), m_global_trans(global_trans) {}
|
||||
|
||||
bool operator()(const StdMeshFace& face1, const StdMeshFace& face2) const
|
||||
{
|
||||
|
@ -54,8 +51,9 @@ namespace
|
|||
case StdMeshInstance::FO_FarthestToNearest:
|
||||
case StdMeshInstance::FO_NearestToFarthest:
|
||||
{
|
||||
float z1 = (OgreToClonk*(m_vertices[face1.Vertices[0]] + m_vertices[face1.Vertices[1]] + m_vertices[face1.Vertices[2]])).z;
|
||||
float z2 = (OgreToClonk*(m_vertices[face2.Vertices[0]] + m_vertices[face2.Vertices[1]] + m_vertices[face2.Vertices[2]])).z;
|
||||
float z1 = (m_global_trans*(m_vertices[face1.Vertices[0]] + m_vertices[face1.Vertices[1]] + m_vertices[face1.Vertices[2]])).z;
|
||||
float z2 = (m_global_trans*(m_vertices[face2.Vertices[0]] + m_vertices[face2.Vertices[1]] + m_vertices[face2.Vertices[2]])).z;
|
||||
|
||||
if (m_inst.GetFaceOrdering() == StdMeshInstance::FO_FarthestToNearest)
|
||||
return z1 < z2;
|
||||
else
|
||||
|
@ -534,6 +532,12 @@ StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs)
|
|||
return rhs * lhs;
|
||||
}
|
||||
|
||||
StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs)
|
||||
{
|
||||
lhs = lhs * rhs;
|
||||
return lhs;
|
||||
}
|
||||
|
||||
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs)
|
||||
{
|
||||
StdMeshMatrix m;
|
||||
|
@ -1195,7 +1199,7 @@ void StdMeshInstance::SetFaceOrdering(FaceOrdering ordering)
|
|||
}
|
||||
}
|
||||
|
||||
BoneTransformsDirty = true;
|
||||
//BoneTransformsDirty = true;
|
||||
|
||||
// Update attachments (only own meshes for now... others might be displayed both attached and non-attached...)
|
||||
// still not optimal.
|
||||
|
@ -1205,6 +1209,23 @@ void StdMeshInstance::SetFaceOrdering(FaceOrdering ordering)
|
|||
}
|
||||
}
|
||||
|
||||
void StdMeshInstance::SetFaceOrderingForClrModulation(uint32_t clrmod)
|
||||
{
|
||||
// TODO: This could do face ordering only for non-opaque submeshes
|
||||
|
||||
bool opaque = true;
|
||||
for(unsigned int i = 0; i < SubMeshInstances.size(); ++i)
|
||||
if(!SubMeshInstances[i]->Material->IsOpaque())
|
||||
{ opaque = false; break; }
|
||||
|
||||
if(!opaque)
|
||||
SetFaceOrdering(FO_FarthestToNearest);
|
||||
else if( ((clrmod >> 24) & 0xff) != 0xff)
|
||||
SetFaceOrdering(FO_NearestToFarthest);
|
||||
else
|
||||
SetFaceOrdering(FO_Fixed);
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight)
|
||||
{
|
||||
const StdMeshAnimation* animation = Mesh.GetAnimationByName(animation_name);
|
||||
|
@ -1483,8 +1504,10 @@ StdMeshInstance::AttachedMesh* StdMeshInstance::GetAttachedMeshByNumber(unsigned
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void StdMeshInstance::UpdateBoneTransforms()
|
||||
bool StdMeshInstance::UpdateBoneTransforms()
|
||||
{
|
||||
bool was_dirty = BoneTransformsDirty;
|
||||
|
||||
// Nothing changed since last time
|
||||
if (BoneTransformsDirty)
|
||||
{
|
||||
|
@ -1558,9 +1581,6 @@ void StdMeshInstance::UpdateBoneTransforms()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentFaceOrdering != FO_Fixed)
|
||||
ReorderFaces();
|
||||
}
|
||||
|
||||
// Update attachment's attach transformations. Note this is done recursively.
|
||||
|
@ -1572,6 +1592,8 @@ void StdMeshInstance::UpdateBoneTransforms()
|
|||
|
||||
if (BoneTransformsDirty || ChildBoneTransformsDirty || attach->FinalTransformDirty)
|
||||
{
|
||||
was_dirty = true;
|
||||
|
||||
// Compute matrix to change the coordinate system to the one of the attached bone:
|
||||
// The idea is that a vertex at the child bone's position transforms to the parent bone's position.
|
||||
// Therefore (read from right to left) we first apply the inverse of the child bone transformation,
|
||||
|
@ -1594,6 +1616,21 @@ void StdMeshInstance::UpdateBoneTransforms()
|
|||
}
|
||||
|
||||
BoneTransformsDirty = false;
|
||||
return was_dirty;
|
||||
}
|
||||
|
||||
void StdMeshInstance::ReorderFaces(StdMeshMatrix* global_trans)
|
||||
{
|
||||
if(CurrentFaceOrdering != FO_Fixed)
|
||||
{
|
||||
for (unsigned int i = 0; i < SubMeshInstances.size(); ++i)
|
||||
{
|
||||
StdMeshInstanceFaceOrderingCmpPred pred(*this, i, global_trans ? *global_trans : StdMeshMatrix::Identity());
|
||||
std::sort(SubMeshInstances[i]->Faces.begin(), SubMeshInstances[i]->Faces.end(), pred);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Also reorder submeshes, attached meshes and include AttachTransformation for attached meshes...
|
||||
}
|
||||
|
||||
void StdMeshInstance::CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory)
|
||||
|
@ -1779,16 +1816,3 @@ bool StdMeshInstance::ExecuteAnimationNode(AnimationNode* node)
|
|||
return true;
|
||||
}
|
||||
|
||||
void StdMeshInstance::ReorderFaces()
|
||||
{
|
||||
for (unsigned int i = 0; i < SubMeshInstances.size(); ++i)
|
||||
{
|
||||
StdMeshInstanceFaceOrderingCmpPred pred(*this, i);
|
||||
std::sort(SubMeshInstances[i]->Faces.begin(), SubMeshInstances[i]->Faces.end(), pred);
|
||||
}
|
||||
|
||||
// TODO: Also reorder submeshes and attached meshes... maybe this face ordering
|
||||
// is not a good idea after all. Another possibility to obtain the effect would be
|
||||
// to first render to an offscreen texture, then render to screen (only for meshes
|
||||
// with halftransparent clrmod applied)
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
StdMeshMatrix operator*(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||
StdMeshMatrix operator*(float lhs, const StdMeshMatrix& rhs);
|
||||
StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs);
|
||||
StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||
StdMeshQuaternion operator-(const StdMeshQuaternion& rhs);
|
||||
StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
||||
|
@ -357,6 +358,7 @@ public:
|
|||
|
||||
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
||||
void SetFaceOrdering(FaceOrdering ordering);
|
||||
void SetFaceOrderingForClrModulation(uint32_t clrmod);
|
||||
|
||||
// Provider for animation position or weight.
|
||||
class ValueProvider
|
||||
|
@ -584,8 +586,22 @@ public:
|
|||
|
||||
// Update bone transformation matrices, vertex positions and final attach transformations of attached children.
|
||||
// This is called recursively for attached children, so there is no need to call it on attached children only
|
||||
// which would also not update its attach transformation. Call this once before rendering.
|
||||
void UpdateBoneTransforms();
|
||||
// which would also not update its attach transformation. Call this once before rendering. Returns true if the
|
||||
// mesh was deformed since the last execution, or false otherwise.
|
||||
bool UpdateBoneTransforms();
|
||||
|
||||
// Orders faces according to current face ordering. Clal this once before rendering if one of the following is true:
|
||||
//
|
||||
// a) the call to UpdateBoneTransforms returns true
|
||||
// b) a submesh's material was changed
|
||||
// c) the global transformation changed since previous call to ReorderFaces()
|
||||
// d) some other obscure state change occurred (?)
|
||||
//
|
||||
// global_trans is a global transformation that is applied when rendering the mesh, and this is used
|
||||
// to correctly do face ordering.
|
||||
//
|
||||
// TODO: Should maybe introduce a FaceOrderingDirty flag
|
||||
void ReorderFaces(StdMeshMatrix* global_trans);
|
||||
|
||||
void CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory);
|
||||
void EnumeratePointers();
|
||||
|
@ -598,7 +614,6 @@ protected:
|
|||
|
||||
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create);
|
||||
bool ExecuteAnimationNode(AnimationNode* node);
|
||||
void ReorderFaces();
|
||||
|
||||
FaceOrdering CurrentFaceOrdering;
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ namespace
|
|||
{ "scroll_y", StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_Y },
|
||||
{ "rotate", StdMeshMaterialTextureUnit::Transformation::XF_ROTATE },
|
||||
{ "scale_x", StdMeshMaterialTextureUnit::Transformation::XF_SCALE_X },
|
||||
{ "scale_y", StdMeshMaterialTextureUnit::Transformation::XF_SCALE_Y }
|
||||
{ "scale_y", StdMeshMaterialTextureUnit::Transformation::XF_SCALE_Y },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const Enumerator<StdMeshMaterialTextureUnit::Transformation::WaveType> WaveTypeEnumerators[] =
|
||||
|
@ -135,14 +136,40 @@ namespace
|
|||
{ "triangle", StdMeshMaterialTextureUnit::Transformation::W_TRIANGLE },
|
||||
{ "square", StdMeshMaterialTextureUnit::Transformation::W_SQUARE },
|
||||
{ "sawtooth", StdMeshMaterialTextureUnit::Transformation::W_SAWTOOTH },
|
||||
{ "inverse_sawtooth", StdMeshMaterialTextureUnit::Transformation::W_INVERSE_SAWTOOTH }
|
||||
{ "inverse_sawtooth", StdMeshMaterialTextureUnit::Transformation::W_INVERSE_SAWTOOTH },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const Enumerator<StdMeshMaterialPass::CullHardwareType> CullHardwareEnumerators[] =
|
||||
{
|
||||
{ "clockwise", StdMeshMaterialPass::CH_Clockwise },
|
||||
{ "anticlockwise", StdMeshMaterialPass::CH_CounterClockwise },
|
||||
{ "none", StdMeshMaterialPass::CH_None }
|
||||
{ "none", StdMeshMaterialPass::CH_None },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const Enumerator<StdMeshMaterialPass::SceneBlendType> SceneBlendEnumerators[] =
|
||||
{
|
||||
{ "one", StdMeshMaterialPass::SB_One },
|
||||
{ "zero", StdMeshMaterialPass::SB_Zero },
|
||||
{ "dest_colour", StdMeshMaterialPass::SB_DestColor },
|
||||
{ "src_colour", StdMeshMaterialPass::SB_SrcColor },
|
||||
{ "one_minus_dest_colour", StdMeshMaterialPass::SB_OneMinusDestColor },
|
||||
{ "one_minus_src_colour", StdMeshMaterialPass::SB_OneMinusSrcColor },
|
||||
{ "dest_alpha", StdMeshMaterialPass::SB_DestAlpha },
|
||||
{ "src_alpha", StdMeshMaterialPass::SB_SrcAlpha },
|
||||
{ "one_minus_dest_alpha", StdMeshMaterialPass::SB_OneMinusDestAlpha },
|
||||
{ "one_minus_src_alpha", StdMeshMaterialPass::SB_OneMinusSrcAlpha },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
const EnumeratorShortcut<2, StdMeshMaterialPass::SceneBlendType> SceneBlendShortcuts[] =
|
||||
{
|
||||
{ "add", { StdMeshMaterialPass::SB_One, StdMeshMaterialPass::SB_One } },
|
||||
{ "modulate", { StdMeshMaterialPass::SB_DestColor, StdMeshMaterialPass::SB_Zero } },
|
||||
{ "colour_blend", { StdMeshMaterialPass::SB_SrcColor, StdMeshMaterialPass::SB_OneMinusSrcColor } },
|
||||
{ "alpha_blend", { StdMeshMaterialPass::SB_SrcAlpha, StdMeshMaterialPass::SB_OneMinusSrcAlpha } },
|
||||
{ NULL }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -802,6 +829,7 @@ StdMeshMaterialPass::StdMeshMaterialPass():
|
|||
Specular[0] = Specular[1] = Specular[2] = 0.0f; Specular[3] = 0.0f;
|
||||
Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 0.0f;
|
||||
Shininess = 0.0f;
|
||||
SceneBlendFactors[0] = SB_One; SceneBlendFactors[1] = SB_Zero;
|
||||
}
|
||||
|
||||
void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
||||
|
@ -855,6 +883,10 @@ void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
|||
{
|
||||
CullHardware = ctx.AdvanceEnum(CullHardwareEnumerators);
|
||||
}
|
||||
else if (token_name == "scene_blend")
|
||||
{
|
||||
ctx.AdvanceEnums<2, StdMeshMaterialPass::SceneBlendType>(SceneBlendEnumerators, SceneBlendShortcuts, SceneBlendFactors);
|
||||
}
|
||||
else
|
||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||
}
|
||||
|
@ -887,6 +919,18 @@ void StdMeshMaterialTechnique::Load(StdMeshMaterialParserCtx& ctx)
|
|||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
||||
}
|
||||
|
||||
bool StdMeshMaterialTechnique::IsOpaque() const
|
||||
{
|
||||
// Technique is opaque if one of the passes is opaque (subsequent
|
||||
// non-opaque passes will just depend on the opaque value drawn in
|
||||
// the previous pass; total result will not depend on original
|
||||
// frame buffer value).
|
||||
for(unsigned int i = 0; i < Passes.size(); ++i)
|
||||
if(Passes[i].IsOpaque())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
StdMeshMaterial::StdMeshMaterial():
|
||||
Line(0), ReceiveShadows(true), BestTechniqueIndex(-1)
|
||||
{
|
||||
|
|
|
@ -240,9 +240,25 @@ public:
|
|||
CH_None
|
||||
};
|
||||
|
||||
enum SceneBlendType
|
||||
{
|
||||
SB_One,
|
||||
SB_Zero,
|
||||
SB_DestColor,
|
||||
SB_SrcColor,
|
||||
SB_OneMinusDestColor,
|
||||
SB_OneMinusSrcColor,
|
||||
SB_DestAlpha,
|
||||
SB_SrcAlpha,
|
||||
SB_OneMinusDestAlpha,
|
||||
SB_OneMinusSrcAlpha
|
||||
};
|
||||
|
||||
StdMeshMaterialPass();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
bool IsOpaque() const { return SceneBlendFactors[1] == SB_Zero; }
|
||||
|
||||
StdCopyStrBuf Name;
|
||||
std::vector<StdMeshMaterialTextureUnit> TextureUnits;
|
||||
|
||||
|
@ -254,6 +270,7 @@ public:
|
|||
|
||||
bool DepthWrite;
|
||||
CullHardwareType CullHardware;
|
||||
SceneBlendType SceneBlendFactors[2];
|
||||
};
|
||||
|
||||
class StdMeshMaterialTechnique
|
||||
|
@ -263,6 +280,8 @@ public:
|
|||
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
bool IsOpaque() const;
|
||||
|
||||
StdCopyStrBuf Name;
|
||||
std::vector<StdMeshMaterialPass> Passes;
|
||||
|
||||
|
@ -277,6 +296,8 @@ public:
|
|||
StdMeshMaterial();
|
||||
void Load(StdMeshMaterialParserCtx& ctx);
|
||||
|
||||
bool IsOpaque() const { assert(BestTechniqueIndex >= 0); return Techniques[BestTechniqueIndex].IsOpaque(); }
|
||||
|
||||
// Location the Material was loaded from
|
||||
StdCopyStrBuf FileName;
|
||||
unsigned int Line;
|
||||
|
|
Loading…
Reference in New Issue