Pada postingan saya kali ini, saya akan berbagi secuil ilmu yang saya miliki dalam pembuatan projek animasi dengan menggunakan OGRE.

Berhubung saya juga adalah seorang pemula dalam bidang animation dengan OGRE ini, maka saya minta maaf sebelumnya jika penjelasan saya pada penulisan ini kurang jelas. CMIIW

Nah, sekarang langsung aja deh kita bahas tentang projek apa yang saya bikin dengan menggunakan OGRE.
Bahasa pemrograman yang saya gunakan dalam pembuatan projek ini adalah C++ dengan menggunakan Eclipse IDE C++ dengan Ogre SDK yang digunakan sebagai perendernya.

Cara pembuatan suatu projek dari awal, sudah saya jelaskan di penulisan saya yang sebelumnya. Jadi, sekarang saya hanya akan berbagi source code nya saja kepada Anda semua.


Berikut source code yang saya gunakan untuk projek ini :


#include “ExampleApplication.h”
#include “OgreHardwarePixelBuffer.h”
// Hacky globals
Camera* theCam;
Entity* pPlaneEnt;
std::vector aboveWaterEnts;
std::vector belowWaterEnts;

// Fish!
#define NUM_FISH 30
#define NUM_FISH_WAYPOINTS 10
#define FISH_PATH_LENGTH 200
#define FISH_SCALE 1.2
AnimationState* fishAnimations[NUM_FISH];
SimpleSpline fishSplines[NUM_FISH];
Vector3 fishLastPosition[NUM_FISH];
SceneNode* fishNodes[NUM_FISH];
Real animTime = 0.0f;

Plane reflectionPlane;

class RefractionTextureListener : public RenderTargetListener
{
public:
void preRenderTargetUpdate(const RenderTargetEvent& evt)
{
// Hide plane and objects above the water
pPlaneEnt->setVisible(false);
std::vector::iterator i, iend;
iend = aboveWaterEnts.end();
for (i = aboveWaterEnts.begin(); i != iend; ++i)
{
(*i)->setVisible(false);
}

}
void postRenderTargetUpdate(const RenderTargetEvent& evt)
{
// Show plane and objects above the water
pPlaneEnt->setVisible(true);
std::vector::iterator i, iend;
iend = aboveWaterEnts.end();
for (i = aboveWaterEnts.begin(); i != iend; ++i)
{
(*i)->setVisible(true);
}
}

};
class ReflectionTextureListener : public RenderTargetListener
{
public:
void preRenderTargetUpdate(const RenderTargetEvent& evt)
{
// Hide plane and objects below the water
pPlaneEnt->setVisible(false);
std::vector::iterator i, iend;
iend = belowWaterEnts.end();
for (i = belowWaterEnts.begin(); i != iend; ++i)
{
(*i)->setVisible(false);
}
theCam->enableReflection(reflectionPlane);

}
void postRenderTargetUpdate(const RenderTargetEvent& evt)
{
// Show plane and objects below the water
pPlaneEnt->setVisible(true);
std::vector::iterator i, iend;
iend = belowWaterEnts.end();
for (i = belowWaterEnts.begin(); i != iend; ++i)
{
(*i)->setVisible(true);
}
theCam->disableReflection();
}

};

class FresnelFrameListener : public ExampleFrameListener
{
public:

FresnelFrameListener(RenderWindow* win, Camera* cam)
: ExampleFrameListener(win, cam, false, false)
{}
bool frameStarted(const FrameEvent &evt)
{
animTime += evt.timeSinceLastFrame;
while (animTime > FISH_PATH_LENGTH)
animTime -= FISH_PATH_LENGTH;

for (size_t fish = 0; fish addTime(evt.timeSinceLastFrame*2);
// Move the fish
Vector3 newPos = fishSplines[fish].interpolate(animTime / FISH_PATH_LENGTH);
fishNodes[fish]->setPosition(newPos);
// Work out the direction
Vector3 direction = fishLastPosition[fish] – newPos;
direction.normalise();
// Test for opposite vectors
Real d = 1.0f + Vector3::UNIT_X.dotProduct(direction);
if (fabs(d) setOrientation(orientation);
}
else
{
fishNodes[fish]->setOrientation(
Vector3::UNIT_X.getRotationTo(direction));
}
fishLastPosition[fish] = newPos;

}

return ExampleFrameListener::frameStarted(evt);
}

};

class FresnelApplication : public ExampleApplication
{
protected:
RefractionTextureListener mRefractionListener;
ReflectionTextureListener mReflectionListener;
public:
FresnelApplication() {

}

~FresnelApplication()
{
}
protected:

// Just override the mandatory create scene method
void createScene(void)
{

// Check prerequisites first
const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM)))
{
OGRE_EXCEPT(1, “Your card does not support vertex and fragment programs, so cannot ”
“run this demo. Sorry!”,
“Fresnel::createScene”);
}
else
{
if (!GpuProgramManager::getSingleton().isSyntaxSupported(“arbfp1”) &&
!GpuProgramManager::getSingleton().isSyntaxSupported(“ps_2_0”) &&
!GpuProgramManager::getSingleton().isSyntaxSupported(“ps_1_4”)
)
{
OGRE_EXCEPT(1, “Your card does not support advanced fragment programs, ”
“so cannot run this demo. Sorry!”,
“Fresnel::createScene”);
}
}

theCam = mCamera;
theCam->setPosition(-50,125,760);
theCam->setDirection (0,0,-1);
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

// Create a point light
Light* l = mSceneMgr->createLight(“MainLight”);
l->setType(Light::LT_DIRECTIONAL);
l->setDirection(-Vector3::UNIT_Y);

Entity* pEnt;

TexturePtr mTexture = TextureManager::getSingleton().createManual( “Refraction”,
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );
//RenderTexture* rttTex = mRoot->getRenderSystem()->createRenderTexture( “Refraction”, 512, 512 );
RenderTarget *rttTex = mTexture->getBuffer()->getRenderTarget();

{
Viewport *v = rttTex->addViewport( mCamera );
MaterialPtr mat = MaterialManager::getSingleton().getByName(“Examples/FresnelReflectionRefraction”);
mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName(“Refraction”);
v->setOverlaysEnabled(false);
rttTex->addListener(&mRefractionListener);
}

mTexture = TextureManager::getSingleton().createManual( “Reflection”,
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );
//rttTex = mRoot->getRenderSystem()->createRenderTexture( “Reflection”, 512, 512 );
rttTex = mTexture->getBuffer()->getRenderTarget();
{
Viewport *v = rttTex->addViewport( mCamera );
MaterialPtr mat = MaterialManager::getSingleton().getByName(“Examples/FresnelReflectionRefraction”);
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName(“Reflection”);
v->setOverlaysEnabled(false);
rttTex->addListener(&mReflectionListener);
}

// Define a floor plane mesh
reflectionPlane.normal = Vector3::UNIT_Y;
reflectionPlane.d = 0;
MeshManager::getSingleton().createPlane(“ReflectPlane”,
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
reflectionPlane,
700,1300,10,10,true,1,3,5,Vector3::UNIT_Z);
pPlaneEnt = mSceneMgr->createEntity( “plane”, “ReflectPlane” );
pPlaneEnt->setMaterialName(“Examples/FresnelReflectionRefraction”);
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

mSceneMgr->setSkyBox(true, “Examples/CloudyNoonSkyBox”);

// My node to which all objects will be attached
SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();

// above water entities
pEnt = mSceneMgr->createEntity( “RomanBathUpper”, “RomanBathUpper.mesh” );
myRootNode->attachObject(pEnt);
aboveWaterEnts.push_back(pEnt);

pEnt = mSceneMgr->createEntity( “Columns”, “Columns.mesh” );
myRootNode->attachObject(pEnt);
aboveWaterEnts.push_back(pEnt);

Ogre::SceneNode *headNode = myRootNode->createChildSceneNode ();
pEnt = mSceneMgr->createEntity( “OgreHead”, “ogrehead.mesh” );
pEnt->setMaterialName (“RomanBath/OgreStone”);
headNode->attachObject(pEnt);
headNode->setPosition(-350,55,130);
headNode->rotate(Vector3::UNIT_Y, Degree (90));
aboveWaterEnts.push_back(pEnt);

// below water entities
pEnt = mSceneMgr->createEntity( “RomanBathLower”, “RomanBathLower.mesh” );
myRootNode->attachObject(pEnt);
belowWaterEnts.push_back(pEnt);

for (size_t fishNo = 0; fishNo createEntity(“fish” + StringConverter::toString(fishNo), “fish.mesh”);
fishNodes[fishNo] = myRootNode->createChildSceneNode();
fishNodes[fishNo]->setScale(FISH_SCALE, FISH_SCALE, FISH_SCALE);
fishAnimations[fishNo] = pEnt->getAnimationState(“swim”);
fishAnimations[fishNo]->setEnabled(true);
fishNodes[fishNo]->attachObject(pEnt);
belowWaterEnts.push_back(pEnt);

// Generate a random selection of points for the fish to swim to
fishSplines[fishNo].setAutoCalculate(false);
Vector3 lastPos;
for (size_t waypoint = 0; waypoint 0)
{
// check this waypoint isn’t too far, we don’t want turbo-fish😉
// since the waypoints are achieved every 5 seconds, half the length
// of the pond is ok
while ((lastPos – pos).length() > 750)
{
pos = Vector3(
Math::SymmetricRandom() * 270, -10, Math::SymmetricRandom() * 700);
}
}
fishSplines[fishNo].addPoint(pos);
lastPos = pos;
}
// close the spline
fishSplines[fishNo].addPoint(fishSplines[fishNo].getPoint(0));
// recalc
fishSplines[fishNo].recalcTangents();

}

}

void createFrameListener(void)
{
mFrameListener= new FresnelFrameListener(mWindow, mCamera);
mFrameListener->showDebugOverlay(true);
mRoot->addFrameListener(mFrameListener);
}

};

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include “windows.h”
#endif

#ifdef __cplusplus
extern “C” {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
FresnelApplication app;

try {
app.go();
} catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), “An exception has occured!”, MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
}

return 0;
}

#ifdef __cplusplus
}
#endif

nah, ketika semua package telah di buid…
ketika program telah dijalankan, maka tampilan outpunya akan seperti gambar di bawah ini :

screenshot_1.png
screenshot_2.png
screenshot_3.png

Pada hasil render projek ini, kita bisa menggerakan sudut pandang sesuai dengan keinginan kita dengan menekan tombol arah atau dengan menekal tombol W,S,A,D.