Added animations for mesh objects

stable-5.2
Armin Burgmeier 2009-07-12 16:27:04 +02:00
parent 8501d99173
commit bbc8fa98db
10 changed files with 133 additions and 19 deletions

View File

@ -176,6 +176,7 @@ class C4ActionDef
C4AulScriptFunc *EndCall;
C4AulScriptFunc *AbortCall;
C4AulScriptFunc *PhaseCall;
StdStrBuf Animation;
public:
void Default();
void CompileFunc(StdCompiler *pComp);

View File

@ -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 ----------------------------------------------

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -0,0 +1,5 @@
#strict 2
func Initialize()
{
CreateObject(MONS, LandscapeWidth()/2, LandscapeHeight()/2);
}

View File

@ -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; }

View File

@ -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.

View File

@ -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);
}