forked from Mirrors/openclonk
Added animations for mesh objects
parent
8501d99173
commit
bbc8fa98db
|
@ -176,6 +176,7 @@ class C4ActionDef
|
|||
C4AulScriptFunc *EndCall;
|
||||
C4AulScriptFunc *AbortCall;
|
||||
C4AulScriptFunc *PhaseCall;
|
||||
StdStrBuf Animation;
|
||||
public:
|
||||
void Default();
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
|
|
@ -132,6 +132,7 @@ void C4ActionDef::CompileFunc(StdCompiler *pComp)
|
|||
pComp->Value(mkNamingAdapt(toC4CStr(TurnAction), "TurnAction", "" ));
|
||||
pComp->Value(mkNamingAdapt(Reverse, "Reverse", 0 ));
|
||||
pComp->Value(mkNamingAdapt(Step, "Step", 1 ));
|
||||
pComp->Value(mkNamingAdapt(Animation, "Animation", StdStrBuf() ));
|
||||
}
|
||||
|
||||
//--------------------------------- C4DefCore ----------------------------------------------
|
||||
|
|
|
@ -2251,6 +2251,16 @@ BOOL C4Object::SetPhase(int32_t iPhase)
|
|||
if (Action.Act<=ActIdle) return FALSE;
|
||||
C4ActionDef *actdef=&(Def->ActMap[Action.Act]);
|
||||
Action.Phase=BoundBy<int32_t>(iPhase,0,actdef->Length);
|
||||
Action.PhaseDelay = 0;
|
||||
|
||||
if(pMeshInstance)
|
||||
{
|
||||
if(actdef->Delay)
|
||||
pMeshInstance->SetPosition(static_cast<float>(Action.Phase * actdef->Delay + Action.PhaseDelay) / (actdef->Delay * actdef->Length) * pMeshInstance->GetAnimation()->Length);
|
||||
else
|
||||
pMeshInstance->SetPosition(static_cast<float>(Action.Phase) / actdef->Length * pMeshInstance->GetAnimation()->Length);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -4103,6 +4113,16 @@ BOOL C4Object::SetAction(int32_t iAct, C4Object *pTarget, C4Object *pTarget2, in
|
|||
if (Def && !Inside<int32_t>(iAct,ActIdle,Def->ActNum-1))
|
||||
return FALSE;
|
||||
|
||||
// Set animation on instance. Abort if the mesh does not have
|
||||
// such an animation.
|
||||
if(pMeshInstance)
|
||||
{
|
||||
if(iAct == ActIdle || Def->ActMap[iAct].Animation == "")
|
||||
pMeshInstance->UnsetAnimation();
|
||||
else if(!pMeshInstance->SetAnimationByName(Def->ActMap[iAct].Animation))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Stop previous act sound
|
||||
if (iLastAction>ActIdle)
|
||||
if (iAct!=iLastAction)
|
||||
|
@ -5372,6 +5392,7 @@ void C4Object::ExecAction()
|
|||
if (pAction->Delay)
|
||||
{
|
||||
Action.PhaseDelay+=iPhaseAdvance;
|
||||
bool set_new_action = false;
|
||||
if (Action.PhaseDelay>=pAction->Delay)
|
||||
{
|
||||
// Advance Phase
|
||||
|
@ -5387,12 +5408,23 @@ void C4Object::ExecAction()
|
|||
{
|
||||
// set new action if it's not Hold
|
||||
if (pAction->NextAction==ActHold)
|
||||
{
|
||||
Action.Phase = pAction->Length-1;
|
||||
Action.PhaseDelay = pAction->Delay-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set new action
|
||||
set_new_action = true;
|
||||
SetAction(pAction->NextAction, NULL, NULL, SAC_StartCall | SAC_EndCall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update animation on mesh instance. If a new action was set,
|
||||
// then will already have happened for the new action.
|
||||
if(pMeshInstance && pMeshInstance->GetAnimation() && !set_new_action)
|
||||
pMeshInstance->SetPosition(static_cast<float>(Action.Phase * pAction->Delay + Action.PhaseDelay) / (pAction->Delay * pAction->Length) * pMeshInstance->GetAnimation()->Length);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -10,6 +10,7 @@ NextAction=Walk
|
|||
TurnAction=Turn
|
||||
StartCall=HitCheck
|
||||
InLiquidAction=Swim
|
||||
Animation=Walk
|
||||
|
||||
[Action]
|
||||
Name=Turn
|
||||
|
@ -78,4 +79,4 @@ Delay=1
|
|||
Reverse=1
|
||||
Facet=0,102,48,34
|
||||
NextAction=Walk
|
||||
InLiquidAction=Swim
|
||||
InLiquidAction=Swim
|
||||
|
|
|
@ -20,12 +20,12 @@ private func Activity()
|
|||
if (Random(2) || (GetAction() != "Walk" && GetAction() != "Swim")) return 1;
|
||||
|
||||
// Springen
|
||||
if (GetAction() == "Walk")
|
||||
/* if (GetAction() == "Walk")
|
||||
if (!Random(3)) return DoJump();
|
||||
|
||||
// Umsehen
|
||||
if (GetAction() == "Walk")
|
||||
if (!Random(8)) return SetAction("LookUp");
|
||||
if (!Random(8)) return SetAction("LookUp");*/
|
||||
|
||||
// Umdrehen
|
||||
if (Random(2)) return TurnRight();
|
||||
|
|
|
@ -72,7 +72,6 @@ Liquid=Water-Smooth
|
|||
LiquidLevel=20,30,0,100
|
||||
Layers=Rock=7;Rock=7;Gold=7;Granite=4;Water=5;Earth-earth=50;Earth-earth_dry=50
|
||||
SkyScrollMode=2
|
||||
Animals=MONS=3
|
||||
|
||||
[Weather]
|
||||
Climate=40,10,0,100
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#strict 2
|
||||
func Initialize()
|
||||
{
|
||||
CreateObject(MONS, LandscapeWidth()/2, LandscapeHeight()/2);
|
||||
}
|
|
@ -223,7 +223,8 @@ class StdMeshInstance
|
|||
public:
|
||||
StdMeshInstance(const StdMesh& mesh);
|
||||
|
||||
void SetAnimation(const StdStrBuf& animation_name);
|
||||
bool SetAnimationByName(const StdStrBuf& animation_name);
|
||||
void SetAnimation(const StdMeshAnimation& animation);
|
||||
void UnsetAnimation();
|
||||
|
||||
const StdMeshAnimation* GetAnimation() const { return Animation; }
|
||||
|
|
|
@ -312,8 +312,9 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
const StdMeshBox& box = mesh.GetBoundingBox();
|
||||
|
||||
glPushMatrix();
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_NORMALIZE);
|
||||
//glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
// TODO: Zoom, ClrMod, ...
|
||||
|
@ -321,16 +322,22 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
//glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
|
||||
// Scale so that the mesh fits in (tx,ty,twdt,thgt)
|
||||
double rx = -box.x1 / (box.x2 - box.x1);
|
||||
double ry = -box.y1 / (box.y2 - box.y1);
|
||||
float rx = -box.x1 / (box.x2 - box.x1);
|
||||
float ry = -box.y1 / (box.y2 - box.y1);
|
||||
glTranslatef(tx + rx*twdt, ty + ry*thgt, 0.0f);
|
||||
glScalef(twdt/(box.x2 - box.x1), thgt/(box.y2 - box.y1), 1.0f);
|
||||
|
||||
// Put a light source in front of the object
|
||||
GLfloat light_position[] = { 0.0f, 0.0f, 6.0f, 1.0f };
|
||||
GLfloat light_position[] = { 0.0f, 0.0f, 15.0f, 1.0f };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
float scx = twdt/(box.x2 - box.x1);
|
||||
float scy = thgt/(box.y2 - box.y1);
|
||||
// Keep aspect ratio:
|
||||
//if(scx < scy) scy = scx;
|
||||
//else scx = scy;
|
||||
glScalef(scx, scy, 1.0f);
|
||||
|
||||
// TODO: Find a working technique, we currently always use the
|
||||
// first one:
|
||||
const StdMeshMaterial& material = mesh.GetMaterial();
|
||||
|
@ -347,6 +354,7 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
glMaterialfv(GL_FRONT, GL_SPECULAR, pass.Specular);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, pass.Emissive);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, pass.Shininess);
|
||||
|
||||
// TODO: Set up texture units
|
||||
// Render mesh
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
@ -373,7 +381,7 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw
|
|||
glDisable(GL_LIGHT0);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_NORMALIZE);
|
||||
glShadeModel(GL_FLAT);
|
||||
glPopMatrix();
|
||||
|
||||
// TODO: glScissor, so that we only clear the area the mesh covered.
|
||||
|
|
|
@ -20,6 +20,51 @@
|
|||
|
||||
#include <tinyxml/tinyxml.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Generate matrix to convert the mesh from Ogre coordinate system to Clonk
|
||||
// coordinate system. When making changes here, don't forget to make
|
||||
// corresponding changes for the inverse matrix below.
|
||||
StdMeshMatrix CoordCorrectionMatrix()
|
||||
{
|
||||
StdMeshMatrix matrix;
|
||||
StdMeshMatrix helper;
|
||||
|
||||
//matrix.SetIdentity();
|
||||
matrix.SetScale(-1.0f, 1.0f, 1.0f);
|
||||
|
||||
//helper.SetRotate(M_PI/2.0f, 1.0f, 0.0f, 0.0f);
|
||||
helper.SetRotate(M_PI/2.0f, 1.0f, 0.0f, 0.0f);
|
||||
matrix.Mul(helper);
|
||||
|
||||
helper.SetRotate(M_PI/2.0f, 0.0f, 0.0f, 1.0f);
|
||||
matrix.Mul(helper);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
StdMeshMatrix CoordCorrectionMatrixInverse()
|
||||
{
|
||||
StdMeshMatrix matrix;
|
||||
StdMeshMatrix helper;
|
||||
|
||||
matrix.SetRotate(-M_PI/2.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
//helper.SetRotate(-M_PI/2.0f, 1.0f, 0.0f, 0.0f);
|
||||
helper.SetRotate(-M_PI/2.0f, 1.0f, 0.0f, 0.0f);
|
||||
matrix.Mul(helper);
|
||||
|
||||
//helper.SetIdentity();
|
||||
helper.SetScale(-1.0f, 1.0f, 1.0f);
|
||||
matrix.Mul(helper);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
StdMeshMatrix CoordCorrection = CoordCorrectionMatrix();
|
||||
StdMeshMatrix CoordCorrectionInverse = CoordCorrectionMatrixInverse();
|
||||
}
|
||||
|
||||
StdMeshError::StdMeshError(const StdStrBuf& message, const char* file, unsigned int line)
|
||||
{
|
||||
Buf.Format("%s:%u: %s", file, line, message.getData());
|
||||
|
@ -189,10 +234,6 @@ void StdMeshMatrix::Add(const StdMeshMatrix& other)
|
|||
|
||||
void StdMeshMatrix::Transform(const StdMeshMatrix& other)
|
||||
{
|
||||
// StdMeshMatrix blah(other);
|
||||
// bla.Mul(*this);
|
||||
// *this = bla;
|
||||
|
||||
StdMeshMatrix old(*this);
|
||||
|
||||
a[0][0] = other.a[0][0]*old.a[0][0] + other.a[0][1]*old.a[1][0] + other.a[0][2]*old.a[2][0];
|
||||
|
@ -217,8 +258,8 @@ void StdMeshVertex::Transform(const StdMeshMatrix& trans)
|
|||
StdMeshVertex old(*this);
|
||||
|
||||
x = trans(0,0)*old.x + trans(0,1)*old.y + trans(0,2)*old.z + trans(0,3);
|
||||
y = trans(1,0)*old.x + trans(1,1)*old.y + trans(1,2)*old.z + trans(0,3);
|
||||
z = trans(2,0)*old.x + trans(2,1)*old.y + trans(2,2)*old.z + trans(0,3);
|
||||
y = trans(1,0)*old.x + trans(1,1)*old.y + trans(1,2)*old.z + trans(1,3);
|
||||
z = trans(2,0)*old.x + trans(2,1)*old.y + trans(2,2)*old.z + trans(2,3);
|
||||
nx = trans(0,0)*old.nx + trans(0,1)*old.ny + trans(0,2)*old.nz;
|
||||
ny = trans(1,0)*old.nx + trans(1,1)*old.ny + trans(0,2)*old.nz;
|
||||
nz = trans(2,0)*old.nx + trans(2,1)*old.ny + trans(2,2)*old.nz;
|
||||
|
@ -364,6 +405,9 @@ void StdMesh::InitXML(const char* filename, const char* xml_data, StdMeshSkeleto
|
|||
Vertices[i].u = mesh.RequireFloatAttribute(texcoord_elem, "u");
|
||||
Vertices[i].v = mesh.RequireFloatAttribute(texcoord_elem, "v");
|
||||
|
||||
// Convert to Clonk coordinate system
|
||||
Vertices[i].Transform(CoordCorrection);
|
||||
|
||||
// Construct BoundingBox
|
||||
if(i == 0)
|
||||
{
|
||||
|
@ -446,10 +490,18 @@ void StdMesh::InitXML(const char* filename, const char* xml_data, StdMeshSkeleto
|
|||
bone->Trans.SetRotate(angle, rx, ry, rz);
|
||||
bone->Trans.Transform(helper);
|
||||
|
||||
// Transform to Clonk coordinate system
|
||||
bone->Trans.Mul(CoordCorrectionInverse);
|
||||
bone->Trans.Transform(CoordCorrection);
|
||||
|
||||
helper.SetRotate(-angle, rx, ry, rz);
|
||||
bone->InverseTrans.SetTranslate(-dx, -dy, -dz);
|
||||
bone->InverseTrans.Transform(helper);
|
||||
|
||||
// Transform to Clonk coordinate system
|
||||
bone->InverseTrans.Mul(CoordCorrectionInverse);
|
||||
bone->InverseTrans.Transform(CoordCorrection);
|
||||
|
||||
bone->Parent = NULL;
|
||||
|
||||
// Index of bone will be set when building Master Bone Table later
|
||||
|
@ -576,12 +628,17 @@ void StdMesh::InitXML(const char* filename, const char* xml_data, StdMeshSkeleto
|
|||
float ry = skeleton.RequireFloatAttribute(axis_elem, "y");
|
||||
float rz = skeleton.RequireFloatAttribute(axis_elem, "z");
|
||||
|
||||
// TODO: Make sure the order is correct here - I am not sure about scale
|
||||
StdMeshMatrix helper;
|
||||
frame.Trans.SetRotate(angle, rx, ry, rz);
|
||||
helper.SetScale(sx, sy, sz);
|
||||
frame.Trans.Transform(helper);
|
||||
helper.SetTranslate(-dx, -dy, -dz);
|
||||
frame.Trans.Transform(helper);
|
||||
|
||||
// Transform into Clonk coordinate system
|
||||
frame.Trans.Transform(CoordCorrection);
|
||||
frame.Trans.Mul(CoordCorrectionInverse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,9 +704,18 @@ StdMeshInstance::StdMeshInstance(const StdMesh& mesh):
|
|||
Vertices[i] = Mesh.GetVertex(i);
|
||||
}
|
||||
|
||||
void StdMeshInstance::SetAnimation(const StdStrBuf& animation_name)
|
||||
bool StdMeshInstance::SetAnimationByName(const StdStrBuf& animation_name)
|
||||
{
|
||||
Animation = Mesh.GetAnimationByName(animation_name);
|
||||
const StdMeshAnimation* animation = Mesh.GetAnimationByName(animation_name);
|
||||
if(!animation) return false;
|
||||
SetAnimation(*animation);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StdMeshInstance::SetAnimation(const StdMeshAnimation& animation)
|
||||
{
|
||||
// TODO: Make sure the animation belongs to this mesh
|
||||
Animation = &animation;
|
||||
SetPosition(0.0f);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue