forked from Mirrors/openclonk
Add support for scene_blend in material scripts (#303)
parent
6729c0ca64
commit
e282de55f1
|
@ -6,6 +6,7 @@ material RopeBalloon
|
||||||
pass
|
pass
|
||||||
{
|
{
|
||||||
cull_hardware none
|
cull_hardware none
|
||||||
|
scene_blend src_alpha one_minus_src_alpha
|
||||||
|
|
||||||
ambient 1.500000 1.500000 1.500000 1.000000
|
ambient 1.500000 1.500000 1.500000 1.000000
|
||||||
diffuse 0.640000 0.640000 0.640000 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 (dwClrModulation != 0xffffff) Application.DDraw->ActivateBlitModulation(dwClrModulation);
|
||||||
|
|
||||||
if (pMeshInstance)
|
if (pMeshInstance)
|
||||||
{
|
pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation);
|
||||||
if ( ((dwClrModulation >> 24) & 0xff) != 0xff)
|
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
else
|
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (eMode == MODE_Rank)
|
if (eMode == MODE_Rank)
|
||||||
{
|
{
|
||||||
|
@ -1174,12 +1169,7 @@ void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj)
|
||||||
if (dwClrModulation != 0xffffff) Application.DDraw->ActivateBlitModulation(dwClrModulation);
|
if (dwClrModulation != 0xffffff) Application.DDraw->ActivateBlitModulation(dwClrModulation);
|
||||||
|
|
||||||
if (pMeshInstance)
|
if (pMeshInstance)
|
||||||
{
|
pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation);
|
||||||
if ( ((dwClrModulation >> 24) & 0xff) != 0xff)
|
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
else
|
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// draw at given rect
|
// draw at given rect
|
||||||
if (!pMeshInstance)
|
if (!pMeshInstance)
|
||||||
|
|
|
@ -251,8 +251,7 @@ bool C4Object::Init(C4PropList *pDef, C4Object *pCreator,
|
||||||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||||
{
|
{
|
||||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -486,8 +485,7 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp)
|
||||||
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
if (pGraphics->Type == C4DefGraphics::TYPE_Mesh)
|
||||||
{
|
{
|
||||||
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
pMeshInstance = new StdMeshInstance(*pGraphics->Mesh);
|
||||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2847,12 +2845,11 @@ void C4Object::CompileFunc(StdCompiler *pComp)
|
||||||
Action.PhaseDelay=iPhaseDelay;
|
Action.PhaseDelay=iPhaseDelay;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// Set Action animation by slot 0
|
|
||||||
if (pMeshInstance)
|
if (pMeshInstance)
|
||||||
{
|
{
|
||||||
|
// Set Action animation by slot 0
|
||||||
Action.Animation = pMeshInstance->GetRootAnimationForSlot(0);
|
Action.Animation = pMeshInstance->GetRootAnimationForSlot(0);
|
||||||
if ( ((ColorMod >> 24) & 0xff) != 0xff) // Sort faces if the object is transparent
|
pMeshInstance->SetFaceOrderingForClrModulation(ColorMod);
|
||||||
pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if on fire but no effect is present (old-style savegames), re-incinerate
|
// 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
|
// set it
|
||||||
cthr->Obj->ColorMod=clr;
|
cthr->Obj->ColorMod=clr;
|
||||||
if (cthr->Obj->pMeshInstance)
|
if (cthr->Obj->pMeshInstance)
|
||||||
{
|
cthr->Obj->pMeshInstance->SetFaceOrderingForClrModulation(clr);
|
||||||
if ( ((clr >> 24) & 0xff) != 0xff)
|
|
||||||
cthr->Obj->pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_NearestToFarthest);
|
|
||||||
else
|
|
||||||
cthr->Obj->pMeshInstance->SetFaceOrdering(StdMeshInstance::FO_Fixed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// success
|
// success
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -40,6 +40,9 @@ CStdDDraw *lpDDraw=NULL;
|
||||||
CStdPalette *lpDDrawPal=NULL;
|
CStdPalette *lpDDrawPal=NULL;
|
||||||
int iGfxEngine=-1;
|
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)
|
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;
|
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;
|
if (!PrepareRendering(sfcTarget)) return false;
|
||||||
// Update bone matrices and vertex data (note this also updates attach transforms and child transforms)
|
// Update bone matrices and vertex data (note this also updates attach transforms and child transforms)
|
||||||
instance.UpdateBoneTransforms();
|
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
|
// Render mesh
|
||||||
PerformMesh(instance, tx, ty, twdt, thgt, dwPlayerColor, pTransform);
|
PerformMesh(instance, tx, ty, twdt, thgt, dwPlayerColor, pTransform);
|
||||||
// success
|
// success
|
||||||
|
|
|
@ -210,6 +210,8 @@ struct ZoomData
|
||||||
class CStdDDraw
|
class CStdDDraw
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static const StdMeshMatrix OgreToClonk;
|
||||||
|
|
||||||
CStdDDraw(): MaxTexSize(0), Saturation(255) { lpDDrawPal=&Pal; }
|
CStdDDraw(): MaxTexSize(0), Saturation(255) { lpDDrawPal=&Pal; }
|
||||||
virtual ~CStdDDraw() { lpDDraw=NULL; }
|
virtual ~CStdDDraw() { lpDDraw=NULL; }
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -677,7 +677,25 @@ namespace
|
||||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Color);
|
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();
|
const StdMeshMaterial& material = instance.GetMaterial();
|
||||||
assert(material.BestTechniqueIndex != -1);
|
assert(material.BestTechniqueIndex != -1);
|
||||||
|
@ -697,7 +715,7 @@ namespace
|
||||||
// clrmodmap texture needs to be the last texture in that case... we should
|
// clrmodmap texture needs to be the last texture in that case... we should
|
||||||
// change the index to maxtextures-1 instead of 3.
|
// change the index to maxtextures-1 instead of 3.
|
||||||
|
|
||||||
if(!fMod2 && dwModClr == 0xffffffff)
|
if(!(dwBlitMode & C4GFXBLIT_MOD2) && dwModClr == 0xffffffff)
|
||||||
{
|
{
|
||||||
// Fastpath for the easy case
|
// Fastpath for the easy case
|
||||||
glMaterialfv(GL_FRONT, GL_AMBIENT, pass.Ambient);
|
glMaterialfv(GL_FRONT, GL_AMBIENT, pass.Ambient);
|
||||||
|
@ -719,7 +737,7 @@ namespace
|
||||||
// TODO: We could also consider applying dwmod using an additional
|
// TODO: We could also consider applying dwmod using an additional
|
||||||
// texture unit, maybe we can even re-use the one which is reserved for
|
// texture unit, maybe we can even re-use the one which is reserved for
|
||||||
// the clrmodmap texture anyway (+adapt the shader).
|
// the clrmodmap texture anyway (+adapt the shader).
|
||||||
if(!fMod2)
|
if(!(dwBlitMode & C4GFXBLIT_MOD2))
|
||||||
{
|
{
|
||||||
Ambient[0] = pass.Ambient[0] * dwMod[0];
|
Ambient[0] = pass.Ambient[0] * dwMod[0];
|
||||||
Ambient[1] = pass.Ambient[1] * dwMod[1];
|
Ambient[1] = pass.Ambient[1] * dwMod[1];
|
||||||
|
@ -786,6 +804,16 @@ namespace
|
||||||
break;
|
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.
|
// TODO: Use vbo if available.
|
||||||
// Note that we need to do this before we do glTexCoordPointer for the
|
// Note that we need to do this before we do glTexCoordPointer for the
|
||||||
// texture units below, otherwise the texcoordpointer is reset by this
|
// 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;
|
const StdMesh& mesh = instance.Mesh;
|
||||||
|
|
||||||
// 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.GetSubMesh(i), dwModClr, fMod2, dwPlayerColor, parity);
|
RenderSubMeshImpl(instance.GetSubMesh(i), dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Draw attached bone
|
// Draw attached bone
|
||||||
|
@ -1015,7 +1043,7 @@ namespace
|
||||||
// TODO: Take attach transform's parity into account
|
// TODO: Take attach transform's parity into account
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glMultMatrixf(attach_trans_gl);
|
glMultMatrixf(attach_trans_gl);
|
||||||
RenderMeshImpl(*attach->Child, dwModClr, fMod2, dwPlayerColor, parity);
|
RenderMeshImpl(*attach->Child, dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
#if 0
|
#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)
|
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
|
// Field of View for perspective projection, in degrees
|
||||||
static const float FOV = 60.0f;
|
static const float FOV = 60.0f;
|
||||||
static const float TAN_FOV = tan(FOV / 2.0f / 180.0f * M_PI);
|
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;
|
const StdMesh& mesh = instance.Mesh;
|
||||||
|
|
||||||
bool parity = OgreToClonkParity;
|
bool parity = OgreToClonkParity;
|
||||||
|
@ -1112,8 +1136,12 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_LIGHTING);
|
glEnable(GL_LIGHTING);
|
||||||
glEnable(GL_BLEND); // TODO: Shouldn't this always be enabled? - blending does not work for meshes without this though.
|
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
|
// Set up projection matrix first. We do transform and Zoom with the
|
||||||
// projection matrix, so that lighting is applied to the untransformed/unzoomed
|
// 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);
|
ModulateClr(dwModClr, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderMeshImpl(instance, dwModClr, !!(dwBlitMode & C4GFXBLIT_MOD2), dwPlayerColor, parity);
|
RenderMeshImpl(instance, dwModClr, dwBlitMode, dwPlayerColor, parity);
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -30,18 +30,15 @@ std::vector<StdMeshInstance::SerializableValueProvider::IDBase*>* StdMeshInstanc
|
||||||
|
|
||||||
namespace
|
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
|
// Helper to sort faces for FaceOrdering
|
||||||
struct StdMeshInstanceFaceOrderingCmpPred
|
struct StdMeshInstanceFaceOrderingCmpPred
|
||||||
{
|
{
|
||||||
const StdMeshInstance& m_inst;
|
const StdMeshInstance& m_inst;
|
||||||
const StdMeshVertex* m_vertices;
|
const StdMeshVertex* m_vertices;
|
||||||
|
const StdMeshMatrix& m_global_trans;
|
||||||
|
|
||||||
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& inst, unsigned int submesh):
|
StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& inst, unsigned int submesh, const StdMeshMatrix& global_trans):
|
||||||
m_inst(inst), m_vertices(m_inst.GetSubMesh(submesh).GetVertices()) {}
|
m_inst(inst), m_vertices(m_inst.GetSubMesh(submesh).GetVertices()), m_global_trans(global_trans) {}
|
||||||
|
|
||||||
bool operator()(const StdMeshFace& face1, const StdMeshFace& face2) const
|
bool operator()(const StdMeshFace& face1, const StdMeshFace& face2) const
|
||||||
{
|
{
|
||||||
|
@ -54,8 +51,9 @@ namespace
|
||||||
case StdMeshInstance::FO_FarthestToNearest:
|
case StdMeshInstance::FO_FarthestToNearest:
|
||||||
case StdMeshInstance::FO_NearestToFarthest:
|
case StdMeshInstance::FO_NearestToFarthest:
|
||||||
{
|
{
|
||||||
float z1 = (OgreToClonk*(m_vertices[face1.Vertices[0]] + m_vertices[face1.Vertices[1]] + m_vertices[face1.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 = (OgreToClonk*(m_vertices[face2.Vertices[0]] + m_vertices[face2.Vertices[1]] + m_vertices[face2.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)
|
if (m_inst.GetFaceOrdering() == StdMeshInstance::FO_FarthestToNearest)
|
||||||
return z1 < z2;
|
return z1 < z2;
|
||||||
else
|
else
|
||||||
|
@ -534,6 +532,12 @@ StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs)
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs)
|
||||||
|
{
|
||||||
|
lhs = lhs * rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs)
|
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs)
|
||||||
{
|
{
|
||||||
StdMeshMatrix m;
|
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...)
|
// Update attachments (only own meshes for now... others might be displayed both attached and non-attached...)
|
||||||
// still not optimal.
|
// 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)
|
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight)
|
||||||
{
|
{
|
||||||
const StdMeshAnimation* animation = Mesh.GetAnimationByName(animation_name);
|
const StdMeshAnimation* animation = Mesh.GetAnimationByName(animation_name);
|
||||||
|
@ -1483,8 +1504,10 @@ StdMeshInstance::AttachedMesh* StdMeshInstance::GetAttachedMeshByNumber(unsigned
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdMeshInstance::UpdateBoneTransforms()
|
bool StdMeshInstance::UpdateBoneTransforms()
|
||||||
{
|
{
|
||||||
|
bool was_dirty = BoneTransformsDirty;
|
||||||
|
|
||||||
// Nothing changed since last time
|
// Nothing changed since last time
|
||||||
if (BoneTransformsDirty)
|
if (BoneTransformsDirty)
|
||||||
{
|
{
|
||||||
|
@ -1558,9 +1581,6 @@ void StdMeshInstance::UpdateBoneTransforms()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentFaceOrdering != FO_Fixed)
|
|
||||||
ReorderFaces();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update attachment's attach transformations. Note this is done recursively.
|
// Update attachment's attach transformations. Note this is done recursively.
|
||||||
|
@ -1572,6 +1592,8 @@ void StdMeshInstance::UpdateBoneTransforms()
|
||||||
|
|
||||||
if (BoneTransformsDirty || ChildBoneTransformsDirty || attach->FinalTransformDirty)
|
if (BoneTransformsDirty || ChildBoneTransformsDirty || attach->FinalTransformDirty)
|
||||||
{
|
{
|
||||||
|
was_dirty = true;
|
||||||
|
|
||||||
// Compute matrix to change the coordinate system to the one of the attached bone:
|
// 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.
|
// 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,
|
// 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;
|
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)
|
void StdMeshInstance::CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory)
|
||||||
|
@ -1779,16 +1816,3 @@ bool StdMeshInstance::ExecuteAnimationNode(AnimationNode* node)
|
||||||
return true;
|
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*(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||||
StdMeshMatrix operator*(float lhs, const StdMeshMatrix& rhs);
|
StdMeshMatrix operator*(float lhs, const StdMeshMatrix& rhs);
|
||||||
StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs);
|
StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs);
|
||||||
|
StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||||
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs);
|
||||||
StdMeshQuaternion operator-(const StdMeshQuaternion& rhs);
|
StdMeshQuaternion operator-(const StdMeshQuaternion& rhs);
|
||||||
StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs);
|
||||||
|
@ -357,6 +358,7 @@ public:
|
||||||
|
|
||||||
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; }
|
||||||
void SetFaceOrdering(FaceOrdering ordering);
|
void SetFaceOrdering(FaceOrdering ordering);
|
||||||
|
void SetFaceOrderingForClrModulation(uint32_t clrmod);
|
||||||
|
|
||||||
// Provider for animation position or weight.
|
// Provider for animation position or weight.
|
||||||
class ValueProvider
|
class ValueProvider
|
||||||
|
@ -584,8 +586,22 @@ public:
|
||||||
|
|
||||||
// Update bone transformation matrices, vertex positions and final attach transformations of attached children.
|
// 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
|
// 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.
|
// which would also not update its attach transformation. Call this once before rendering. Returns true if the
|
||||||
void UpdateBoneTransforms();
|
// 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 CompileFunc(StdCompiler* pComp, AttachedMesh::DenumeratorFactoryFunc Factory);
|
||||||
void EnumeratePointers();
|
void EnumeratePointers();
|
||||||
|
@ -598,7 +614,6 @@ protected:
|
||||||
|
|
||||||
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create);
|
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create);
|
||||||
bool ExecuteAnimationNode(AnimationNode* node);
|
bool ExecuteAnimationNode(AnimationNode* node);
|
||||||
void ReorderFaces();
|
|
||||||
|
|
||||||
FaceOrdering CurrentFaceOrdering;
|
FaceOrdering CurrentFaceOrdering;
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,8 @@ namespace
|
||||||
{ "scroll_y", StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_Y },
|
{ "scroll_y", StdMeshMaterialTextureUnit::Transformation::XF_SCROLL_Y },
|
||||||
{ "rotate", StdMeshMaterialTextureUnit::Transformation::XF_ROTATE },
|
{ "rotate", StdMeshMaterialTextureUnit::Transformation::XF_ROTATE },
|
||||||
{ "scale_x", StdMeshMaterialTextureUnit::Transformation::XF_SCALE_X },
|
{ "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[] =
|
const Enumerator<StdMeshMaterialTextureUnit::Transformation::WaveType> WaveTypeEnumerators[] =
|
||||||
|
@ -135,14 +136,40 @@ namespace
|
||||||
{ "triangle", StdMeshMaterialTextureUnit::Transformation::W_TRIANGLE },
|
{ "triangle", StdMeshMaterialTextureUnit::Transformation::W_TRIANGLE },
|
||||||
{ "square", StdMeshMaterialTextureUnit::Transformation::W_SQUARE },
|
{ "square", StdMeshMaterialTextureUnit::Transformation::W_SQUARE },
|
||||||
{ "sawtooth", StdMeshMaterialTextureUnit::Transformation::W_SAWTOOTH },
|
{ "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[] =
|
const Enumerator<StdMeshMaterialPass::CullHardwareType> CullHardwareEnumerators[] =
|
||||||
{
|
{
|
||||||
{ "clockwise", StdMeshMaterialPass::CH_Clockwise },
|
{ "clockwise", StdMeshMaterialPass::CH_Clockwise },
|
||||||
{ "anticlockwise", StdMeshMaterialPass::CH_CounterClockwise },
|
{ "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;
|
Specular[0] = Specular[1] = Specular[2] = 0.0f; Specular[3] = 0.0f;
|
||||||
Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 0.0f;
|
Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 0.0f;
|
||||||
Shininess = 0.0f;
|
Shininess = 0.0f;
|
||||||
|
SceneBlendFactors[0] = SB_One; SceneBlendFactors[1] = SB_Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
||||||
|
@ -855,6 +883,10 @@ void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx)
|
||||||
{
|
{
|
||||||
CullHardware = ctx.AdvanceEnum(CullHardwareEnumerators);
|
CullHardware = ctx.AdvanceEnum(CullHardwareEnumerators);
|
||||||
}
|
}
|
||||||
|
else if (token_name == "scene_blend")
|
||||||
|
{
|
||||||
|
ctx.AdvanceEnums<2, StdMeshMaterialPass::SceneBlendType>(SceneBlendEnumerators, SceneBlendShortcuts, SceneBlendFactors);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ctx.ErrorUnexpectedIdentifier(token_name);
|
ctx.ErrorUnexpectedIdentifier(token_name);
|
||||||
}
|
}
|
||||||
|
@ -887,6 +919,18 @@ void StdMeshMaterialTechnique::Load(StdMeshMaterialParserCtx& ctx)
|
||||||
ctx.Error(StdCopyStrBuf("'") + token_name.getData() + "' unexpected");
|
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():
|
StdMeshMaterial::StdMeshMaterial():
|
||||||
Line(0), ReceiveShadows(true), BestTechniqueIndex(-1)
|
Line(0), ReceiveShadows(true), BestTechniqueIndex(-1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -240,9 +240,25 @@ public:
|
||||||
CH_None
|
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();
|
StdMeshMaterialPass();
|
||||||
void Load(StdMeshMaterialParserCtx& ctx);
|
void Load(StdMeshMaterialParserCtx& ctx);
|
||||||
|
|
||||||
|
bool IsOpaque() const { return SceneBlendFactors[1] == SB_Zero; }
|
||||||
|
|
||||||
StdCopyStrBuf Name;
|
StdCopyStrBuf Name;
|
||||||
std::vector<StdMeshMaterialTextureUnit> TextureUnits;
|
std::vector<StdMeshMaterialTextureUnit> TextureUnits;
|
||||||
|
|
||||||
|
@ -254,6 +270,7 @@ public:
|
||||||
|
|
||||||
bool DepthWrite;
|
bool DepthWrite;
|
||||||
CullHardwareType CullHardware;
|
CullHardwareType CullHardware;
|
||||||
|
SceneBlendType SceneBlendFactors[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
class StdMeshMaterialTechnique
|
class StdMeshMaterialTechnique
|
||||||
|
@ -263,6 +280,8 @@ public:
|
||||||
|
|
||||||
void Load(StdMeshMaterialParserCtx& ctx);
|
void Load(StdMeshMaterialParserCtx& ctx);
|
||||||
|
|
||||||
|
bool IsOpaque() const;
|
||||||
|
|
||||||
StdCopyStrBuf Name;
|
StdCopyStrBuf Name;
|
||||||
std::vector<StdMeshMaterialPass> Passes;
|
std::vector<StdMeshMaterialPass> Passes;
|
||||||
|
|
||||||
|
@ -277,6 +296,8 @@ public:
|
||||||
StdMeshMaterial();
|
StdMeshMaterial();
|
||||||
void Load(StdMeshMaterialParserCtx& ctx);
|
void Load(StdMeshMaterialParserCtx& ctx);
|
||||||
|
|
||||||
|
bool IsOpaque() const { assert(BestTechniqueIndex >= 0); return Techniques[BestTechniqueIndex].IsOpaque(); }
|
||||||
|
|
||||||
// Location the Material was loaded from
|
// Location the Material was loaded from
|
||||||
StdCopyStrBuf FileName;
|
StdCopyStrBuf FileName;
|
||||||
unsigned int Line;
|
unsigned int Line;
|
||||||
|
|
Loading…
Reference in New Issue