History: IntermediateTutorial6Source
Source of version: 3
Copy to clipboard
This is the source for ((Intermediate Tutorial 6)).
{CODE(wrap="1", colors="c++")} #include "ExampleApplication.h"
// A FrameListener that gets passed our projector node and decal frustum so they can be animated
class ProjectiveDecalListener : public ExampleFrameListener
{
public:
ProjectiveDecalListener(RenderWindow* win, Camera* cam, SceneNode *proj, Frustum *decal)
: ExampleFrameListener(win, cam), mProjectorNode(proj), mDecalFrustum(decal), mAnim(0)
{
}
bool frameStarted(const FrameEvent& evt)
{
// rotate projector about Y at 10 degrees per second
mProjectorNode->rotate(Vector3::UNIT_Y, Degree(evt.timeSinceLastFrame * 10));
// 2 second animation loop
mAnim += evt.timeSinceLastFrame / 2;
if (mAnim >= 1)
mAnim -= 1;
// animate the FOV of the decal frustum between 5 and 25 degrees
mDecalFrustum->setFOVy(Degree(15 + Math::Sin(mAnim * Math::TWO_PI) * 10));
return ExampleFrameListener::frameStarted(evt);
}
protected:
SceneNode *mProjectorNode;
Frustum *mDecalFrustum;
float mAnim;
};
class ProjectiveDecalApplication : public ExampleApplication
{
protected:
SceneNode *mProjectorNode;
Frustum *mDecalFrustum;
Frustum *mFilterFrustum;
void createScene()
{
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
// Create a light
Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
// Position the camera
mCamera->setPosition(60, 200, 70);
mCamera->lookAt(0,0,0);
// Make 6 ogre heads (named head0, head1, etc.) arranged in a circle
Entity *ent;
for (int i = 0; i < 6; i++)
{
SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
ent = mSceneMgr->createEntity("head" + StringConverter::toString(i), "ogrehead.mesh");
headNode->attachObject(ent);
Radian angle(i * Math::TWO_PI / 6);
headNode->setPosition(75 * Math::Cos(angle), 0, 75 * Math::Sin(angle));
}
// Create the decal projector
createProjector();
// Make all of the materials in the head entities receive the decal
for (unsigned int i = 0; i < ent->getNumSubEntities(); i++)
makeMaterialReceiveDecal(ent->getSubEntity(i)->getMaterialName());
}
// The function to create our decal projector
void createProjector()
{
// set up the main decal projection frustum
mDecalFrustum = new Frustum();
mProjectorNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("DecalProjectorNode");
mProjectorNode->attachObject(mDecalFrustum);
mProjectorNode->setPosition(0,5,0);
// include these two lines if you don't want perspective projection
//mDecalFrustum->setProjectionType(PT_ORTHOGRAPHIC);
//mDecalFrustum->setNearClipDistance(25);
// set up the perpendicular filter texture frustum
mFilterFrustum = new Frustum();
mFilterFrustum->setProjectionType(PT_ORTHOGRAPHIC);
SceneNode *filterNode = mProjectorNode->createChildSceneNode("DecalFilterNode");
filterNode->attachObject(mFilterFrustum);
filterNode->setOrientation(Quaternion(Degree(90),Vector3::UNIT_Y));
// load the images for the decal and the filter
//TextureManager::getSingleton().load("decal.png", "General", TEX_TYPE_2D, 1);
//TextureManager::getSingleton().load("decal_filter.png", "General", TEX_TYPE_1D, 1);
}
// A function to take an existing material and make it receive the projected decal
void makeMaterialReceiveDecal(const String &matName)
{
// get the material
MaterialPtr mat = (MaterialPtr)MaterialManager::getSingleton().getByName(matName);
// create a new pass in the material to render the decal
Pass *pass = mat->getTechnique(0)->createPass();
// set our pass to blend the decal over the model's regular texture
pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
pass->setDepthBias(1);
// set the decal to be self illuminated instead of lit by scene lighting
pass->setLightingEnabled(false);
// set up the decal's texture unit
TextureUnitState *texState = pass->createTextureUnitState("decal.png");
texState->setProjectiveTexturing(true, mDecalFrustum);
texState->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
texState->setTextureFiltering(FO_POINT, FO_LINEAR, FO_NONE);
// set up the filter texture's texture unit
texState = pass->createTextureUnitState("decal_filter.png");
texState->setProjectiveTexturing(true, mFilterFrustum);
texState->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
texState->setTextureFiltering(TFO_NONE);
}
// Create new frame listener
void createFrameListener(void)
{
mFrameListener= new ProjectiveDecalListener(mWindow, mCamera, mProjectorNode, mDecalFrustum);
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
ProjectiveDecalApplication app;
try {
app.go();
} catch(Exception& e) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBoxA(NULL, e.getFullDescription().c_str(),
"An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occurred: " << e.getFullDescription();
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
{CODE}
{{Ogre Tutorial}}