Supports Motion, Rotation, Scaling and Orientation (No Collision Detection)

By Anthony Chetta - 7/13/99

Materials Needed: Microsoft Visual C++ 5.0+ and Genesis 3D.

The actor entity (called "SpecificActor" for now) will load the actor file in the path you specify. You can then make it rotate on the X, Y or Z axis at the speed you specify. You can scale the actor to the size you want it and you can orientate it on the X, Y and Z axis. Finally, you can play a motion in the actor at the speed you specify. Unfortunately their is no collision detection for the actors. If anyone knows how to add collision detection please tell me (adding GE_ACTOR_COLLIDE didn't work)...This tutorial assumes that you know how to navigate in Visual C++.

Load Visual C++ and open GTest.dsw (located in your Genesis 3D src directory). Go into Fileview. We will now create two files, SpecificActor.h and SpecificActor.c. Goto File->New and select C/C++ Header File. For the filename enter SpecificActor.h and press OK. Goto File->New, select C++ Source File and enter SpecificActor.c for the filename. Hit OK. In Fileview double click SpecificActor.h and add this code to the file:

 


#ifndef SPECIFICACTOR_H
#define SPECIFICACTOR_H

#ifdef __cplusplus
extern "C" {
#endif

#include "Genesis.h"

#pragma warning( disable : 4068 )

// Define the entity for the world editor
#pragma GE_Type("Item.ico")
typedef struct SpecificActor
{
#pragma GE_Private
geFloat lastTime; // Last animation played
geActor * pActor; // Actual actor
geActor_Def * pActorDef; // Actor definition
geFloat startTime; // Animation start time
geVec3d Rotation; // Vector for rotation
#pragma GE_Published
geVec3d Origin; //Origin of entity
geVec3d scale; // Vector for scaling
geVec3d Orientation; // Vector for orientation
char *ActorFile; // Path and file of the actor
char * Motion; // Motion name
float ASpeed; // Speed of animation
float RSpeed; // Speed of rotation
geBoolean RotateX; // Will it rotate on the X axis?
geBoolean RotateY; // Will it rotate on the Y axis?
geBoolean RotateZ; // Will it rotate on the Z axis?

#pragma GE_Origin(Origin)
#pragma GE_DefaultValue(scale, "2.5 2.5 2.5")
#pragma GE_DefaultValue(Orientation, "11 0 0")
#pragma GE_DefaultValue(Rotation, "0 0 0")
#pragma GE_DefaultValue(ActorFile, "")
#pragma GE_DefaultValue(Motion, "Walk")
#pragma GE_DefaultValue(ASpeed, "0.04")
#pragma GE_DefaultValue(RSpeed, "0.03")
#pragma GE_DefaultValue(RotateX, "False")
#pragma GE_DefaultValue(RotateY, "False")
#pragma GE_DefaultValue(RotateZ, "False")

#pragma GE_Documentation(scale, "Amount to scale the actor")
#pragma GE_Documentation(Orientation, "Orientation of the actor")
#pragma GE_Documentation(ActorFile, "Path and file of the actor")
#pragma GE_Documentation(Motion, "Motion name (case sensitive), leave blank for none")
#pragma GE_Documentation(ASpeed, "Speed of the animation. 0.1 = fast, 0.01 = slow, 0.05 = medium, etc.")
#pragma GE_Documentation(RSpeed, "Speed of the rotation. 0.1 = fast, 0.01 = slow, 0.05 = medium, etc.")
#pragma GE_Documentation(RotateX, "Will the actor rotate on the X axis?")
#pragma GE_Documentation(RotateY, "Will the actor rotate on the Y axis?")
#pragma GE_Documentation(RotateZ, "Will the actor rotate on the Z axis?")

} SpecificActor;

// Functions
geBoolean SpecificActor_Spawn(geEngine *Engine, geWorld *World, geVFile *MainFS, geSound_System *SoundSystem);
geBoolean SpecificActor_Render(geWorld *World);

#ifdef __cplusplus
}
#endif

#endif

 


In Fileview double click AreaSound.c and add this code:

 


/****************************************************************************/
/* FILE: specificactor.c */
/* */
/* Copyright (c) 1999, Anthony Chetta; All rights reserved. */
/*
/* Description: Adds a user defined actor to the world with motion, scaling, rotation and orientation */
/****************************************************************************/

#include <windows.h>
#include <math.h>
#include <assert.h>

#include "genesis.h"
#include "ErrorLog.h"

#include "SpecificActor.h"

geBoolean SpecificActor_Spawn(geEngine *Engine, geWorld *World, geVFile *MainFS, geSound_System *SoundSystem)
{
geEntity_EntitySet * Set;
geEntity * Entity;
SpecificActor * SActor;
geVFile *AFile;

Set = geWorld_GetEntitySet(World, "SpecificActor"); // Find the SpecificActor entity in the world
if (Set == NULL)
return GE_TRUE;

for (Entity= geEntity_EntitySetGetNextEntity(Set, NULL); Entity;
Entity= geEntity_EntitySetGetNextEntity(Set, Entity)) {

SActor= (SpecificActor*)geEntity_GetUserData(Entity); // Get data from the entity

AFile = geVFile_OpenNewSystem (NULL, GE_VFILE_TYPE_DOS, SActor->ActorFile, NULL, GE_VFILE_OPEN_READONLY); //Open actor
if (!AFile) // Not found
{
geErrorLog_AddString(-1, "SpecificActor_Spawn: Couldn't Open Actor File: ", SActor->ActorFile);
return GE_FALSE;
}

SActor->pActorDef = geActor_DefCreateFromFile (AFile); // Create actor definition from the file

SActor->pActor = geActor_Create (SActor->pActorDef); // Create the actor from the def

if (geWorld_AddActor (World, SActor->pActor, GE_ACTOR_RENDER_NORMAL, 0xffffffff)== GE_FALSE) // Add actor to world
return GE_FALSE;

}

return GE_TRUE; // Succesful
}

geBoolean SpecificActor_Render(geWorld *World)
{
geEntity_EntitySet *pSet;
geEntity *pEntity;
geBoolean bHasMotion;

pSet = geWorld_GetEntitySet(World, "SpecificActor"); // Find the entity in the world

if (pSet == NULL)
return GE_TRUE;

pEntity= geEntity_EntitySetGetNextEntity(pSet, NULL);
while (pEntity)
{
geVec3d pos; // Vector for actor position
geXForm3d xform; // XForm for translation, rotation, etc.
geMotion *pMotion; // Motion
float motionTime, startTime; // Times for motion

SpecificActor *SActor= (SpecificActor*)geEntity_GetUserData(pEntity); // Get data from entity
geActor_SetScale(SActor->pActor, SActor->scale.X, SActor->scale.Y, SActor->scale.Z); // Scale the actor
pos= SActor->Origin;
geXForm3d_SetIdentity(&xform);
bHasMotion= GE_FALSE;
geXForm3d_RotateX(&xform, SActor->Orientation.X); // Orientate the actor on the X axis
geXForm3d_RotateY(&xform, SActor->Orientation.Y); // Orientate the actor on the Y axis
geXForm3d_RotateZ(&xform, SActor->Orientation.Z); // Orientate the actor on the Z axis

if (SActor->RotateX) // Does actor have X rotration?
{
SActor->Rotation.X = SActor->Rotation.X + SActor->RSpeed; // Do rotation
geXForm3d_RotateX(&xform, SActor->Rotation.X);
}
if (SActor->RotateY) // Does actor have Y rotation?
{
SActor->Rotation.Y = SActor->Rotation.Y + SActor->RSpeed; // Do rotation
geXForm3d_RotateY(&xform, SActor->Rotation.Y);
}
if (SActor->RotateZ) // Does actor have Z rotation?
{
SActor->Rotation.Z = SActor->Rotation.Z + SActor->RSpeed; // Do rotation
geXForm3d_RotateZ(&xform, SActor->Rotation.Z);
}


pMotion = geActor_GetMotionByName(SActor->pActorDef, SActor->Motion); // Check for motion

if (pMotion) // Has motion
{
bHasMotion= GE_FALSE;
geMotion_GetTimeExtents(pMotion, &startTime, &motionTime); // Get motion time
SActor->lastTime = SActor->lastTime + SActor->ASpeed; // Get next frame
if (SActor->lastTime > motionTime) // If finished start over
SActor->lastTime = startTime;
pos = SActor->Origin;
geXForm3d_Translate(&xform, pos.X, pos.Y, pos.Z); // Set actor at entity position
geActor_SetPose(SActor->pActor, pMotion, SActor->lastTime, &xform); // Update frame
}
if (!pMotion) // No motion
{
pos = SActor->Origin;
geXForm3d_Translate(&xform, pos.X, pos.Y, pos.Z); // Set actor at entity position
geActor_ClearPose(SActor->pActor, &xform);
}


pEntity= geEntity_EntitySetGetNextEntity(pSet, pEntity); // Get next entity

}
return GE_TRUE; //Successful
}

 


The main part is done. In Fileview open GameMgr.h, goto line 35 or so and add this code:

// Read The Specific Actor Code
#include "SpecificActor.h"

Open GameMgr.c, goto line 853 or so (careful not to add this in the middle of some other procedure) and add this code:

// Create The SpecificActor
if (!SpecificActor_Spawn(GameMgr_GetEngine(GMgr), GameMgr_GetWorld(GMgr), MainFS, GameMgr_GetSoundSystem(GMgr)))
GenVS_Error("GameMgr_SetWorld: SpecificActor_Spawn failed.\n");

Open Client.c, goto line 2886 or so and add this code:

// Render the SpecificActor
if (!SpecificActor_Render(World))
GenVS_Error("Client_RenderWorld: SpecificActor_Render failed.\n");

That's it! Now build GTest.exe (from the Build menu).

Notes when adding SpecificActor to your level: Instead of typing "C:\dir\actor.act" type "..\dir\actor.act". Animation Speed (ASpeed) should only be increased/decreased in increments of .01 (eg: 0.04, 0.05, etc), the same goes for rotation speed (RSpeed). Motion names are case sensitive. X = 11 for orientation will make most standard actors stand straight up.

Download SpecificActor.h and SpecificActor.c here

Well that's it. I hope this tutorial was helpful. If you have any comments or questions, and if anyone knows how to fix the actor collision, please email me.

Material Copyright© 1999 By Anthony Chetta

7/13/99