packages feed

hogre (empty) → 0.0.1

raw patch · 7 files changed

+981/−0 lines, 7 filesdep +basedep +haskell98setup-changed

Dependencies added: base, haskell98

Files

+ LICENSE view
@@ -0,0 +1,23 @@+Copyright (c) 2009 Antti Salonen++Permission is hereby granted, free of charge, to any person+obtaining a copy of this software and associated documentation+files (the "Software"), to deal in the Software without+restriction, including without limitation the rights to use,+copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following+conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.+
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple+main = defaultMain+
+ TODO view
@@ -0,0 +1,5 @@+-In addition to raySceneQuerySimple, add raySceneQuery which returns [Either Vector3 String]+  - List of intersections with world and entities - entity names by getMovableType() and getName()+-SkyPlanes and SkyBoxes+-Fog+-Differentiate between Entities and StaticGeometry
+ csrc/ogre_c.cpp view
@@ -0,0 +1,427 @@+#include "ogre_c.h"++using namespace Ogre;+using namespace std;++static const char* scenemgrname = "Default SceneManager";+static const char* camnodename = "camnode0";++static const float epsilon = 0.0001f;++static Root *gRoot;+static SceneManager *gMgr;+static Camera *gCam;+static SceneNode *gCamnode;+static RenderWindow *gRenderWindow;+static CEGUI::OgreCEGUIRenderer *gRenderer;+static CEGUI::System *gSystem;+static RaySceneQuery *gRaySceneQuery;++// Local functions+static void createRoot()+{+    gRoot = new Root();+}++static void defineResources(const char* filename)+{+    string secName, typeName, archName;+    ConfigFile cf;+    cf.load(filename);++    ConfigFile::SectionIterator seci = cf.getSectionIterator();+    while (seci.hasMoreElements())+    {+        secName = seci.peekNextKey();+        ConfigFile::SettingsMultiMap *settings = seci.getNext();+        ConfigFile::SettingsMultiMap::iterator i;+        for (i = settings->begin(); i != settings->end(); ++i)+        {+            typeName = i->first;+            archName = i->second;+            ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);+        }+    }+}++static void setupRenderSystem()+{+    if (!gRoot->restoreConfig() && !gRoot->showConfigDialog())+        throw Exception(52, "User canceled the config dialog!", "Application::setupRenderSystem()");+}++static void createRenderWindow(int autocreatewindow, const char* windowtitle)+{+    // gRoot->restoreConfig();+    // gRoot->loadPlugin("RenderSystem_GL");+    // gRoot->loadPlugin("Plugin_CgProgramManager");+    // gRoot->loadPlugin("Plugin_OctreeSceneManager");++    // gRoot->setRenderSystem(*(gRoot->getAvailableRenderers().begin()));+    if(autocreatewindow)+    {+        gRenderWindow = gRoot->initialise(autocreatewindow, windowtitle);+        return;+    }+    gRoot->restoreConfig();+    gRoot->initialise(false);+    Ogre::NameValuePairList misc;+    misc["currentGLContext"] = String("True");+    gRenderWindow = gRoot->createRenderWindow("MainRenderWindow", 640, 480, false, &misc);+    gRenderWindow->setVisible(true);++    // parseWindowGeometry(gRoot->getRenderSystem()->getConfigOptions(), width, height, fullscreen);+    /*+    gRoot->restoreConfig(false);+    ConfigFile::SettingsMultiMap *misc;+    misc["currentGLContext"] = String("True");+    RenderWindow *renderWindow = gRoot->createRenderWindow("MainRenderWindow", 640, 480, false, &misc);+    renderWindow->setVisible(true);+    */+}++static void initializeResourceGroups()+{+    TextureManager::getSingleton().setDefaultNumMipmaps(5);+    ResourceGroupManager::getSingleton().initialiseAllResourceGroups();+}++static void initCamera(float bg_r, float bg_g, float bg_b)+{+    std::cerr << "create camera" << std::endl;+    gCam = gMgr->createCamera("Camera");+    std::cerr << "add viewport" << std::endl;+    // Viewport *vp = gRoot->getAutoCreatedWindow()->addViewport(gCam);+    Viewport *vp = gRenderWindow->addViewport(gCam);++    std::cerr << "set background color" << std::endl;+    vp->setBackgroundColour(ColourValue(bg_r, bg_g, bg_b));+    std::cerr << "set clip" << std::endl;+    gCam->setNearClipDistance(0.5);+    std::cerr << "set ratio" << std::endl;+    gCam->setAutoAspectRatio(true);++    std::cerr << "create node" << std::endl;+    gCamnode = gMgr->getRootSceneNode()->createChildSceneNode(camnodename);+    std::cerr << "attach" << std::endl;+    gCamnode->attachObject(gCam);+}++static void setupCEGUI()+{+    // RenderWindow *win = gRoot->getAutoCreatedWindow();++    gRenderer = new CEGUI::OgreCEGUIRenderer(gRenderWindow, RENDER_QUEUE_OVERLAY, false, 3000, gMgr);+    gSystem = new CEGUI::System(gRenderer);+}++static void setupScene(int shadow_type, int manager_type)+{+    gMgr = gRoot->createSceneManager(manager_type, scenemgrname);++    gMgr->setShadowTechnique(+            shadow_type == 0 ? SHADOWTYPE_NONE : +            shadow_type == 1 ? SHADOWTYPE_STENCIL_MODULATIVE : +            shadow_type == 2 ? SHADOWTYPE_STENCIL_ADDITIVE : +            shadow_type == 3 ? SHADOWTYPE_TEXTURE_MODULATIVE : +            shadow_type == 4 ? SHADOWTYPE_TEXTURE_ADDITIVE : +            shadow_type == 5 ? SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED : +                               SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);+    gRaySceneQuery = gMgr->createRayQuery(Ray());+}++// Exported functions++// Initialization functions+int init(int shadow_type, const char* res_filename, int autocreatewindow, const char* title, +        float bg_r, float bg_g, float bg_b, int manager_type)+{+    std::cerr << "!!! creating root" << std::endl;+    createRoot();+    std::cerr << "!!! defining resources" << std::endl;+    defineResources(res_filename);+    std::cerr << "!!! setting up render system" << std::endl;+    setupRenderSystem();+    std::cerr << "!!! creating render window" << std::endl;+    createRenderWindow(autocreatewindow, title);+    std::cerr << "!!! init resource groups" << std::endl;+    initializeResourceGroups();+    std::cerr << "!!! setup scene" << std::endl;+    setupScene(shadow_type, manager_type);+    std::cerr << "!!! init camera" << std::endl;+    initCamera(bg_r, bg_g, bg_b);+    std::cerr << "!!! setting up cegui" << std::endl;+    setupCEGUI();+    std::cerr << "!!! finished" << std::endl;+    return 0;+}++// Miscellaneous functions+int cleanup()+{+    std::cerr << "destroying query..." << std::endl;+    gMgr->destroyQuery(gRaySceneQuery);+    std::cerr << "destroying renderer..." << std::endl;+    delete gRenderer;+    std::cerr << "destroying system..." << std::endl;+    delete gSystem;+    std::cerr << "destroying root..." << std::endl;+    delete gRoot;+    return 0;+}++int render()+{+    return !(gRoot->renderOneFrame());+}++// Manipulation functions+void setAmbientLight(float ambient_light_r, float ambient_light_g, float ambient_light_b)+{+    gMgr->setAmbientLight(ColourValue( ambient_light_r, ambient_light_g, ambient_light_b) );+}++void setSkyDome(int enabled, const char* texture, float curvature)+{+    gMgr->setSkyDome(enabled, texture, curvature);+}++void setWorldGeometry(const char* cfg)+{+    gMgr->setWorldGeometry(cfg);+}++int newEntity(const char* name, const char* model, int castshadows)+{+    std::stringstream nname;+    nname << "Node_" << name;+    Entity* ent = gMgr->createEntity (name, model);+    ent->setCastShadows(castshadows);+    SceneNode* node = gMgr->getRootSceneNode()->createChildSceneNode(nname.str());+    node->attachObject(ent);+    return 0;+}++void setEntityPosition(const char* name, float x, float y, float z)+{+    gMgr->getEntity(name)->getParentSceneNode()->setPosition(Vector3(x, y, z));+}++void setLightType(const char* lightname, int lighttype)+{+    gMgr->getLight(lightname)->setType(lighttype == 0 ? Light::LT_POINT : lighttype == 1 ? Light::LT_DIRECTIONAL : Light::LT_SPOTLIGHT);+}++void setLightDiffuseColor(const char* lightname, float color_r, float color_g, float color_b)+{+    gMgr->getLight(lightname)->setDiffuseColour(color_r, color_g, color_b);+}++void setLightSpecularColor(const char* lightname, float color_r, float color_g, float color_b)+{+    gMgr->getLight(lightname)->setSpecularColour(color_r, color_g, color_b);+}++void setLightDirection(const char* lightname, float x, float y, float z)+{+    gMgr->getLight(lightname)->setDirection(x, y, z);+}++void setLightPosition(const char* lightname, float x, float y, float z)+{+    gMgr->getLight(lightname)->setPosition(x, y, z);+}++void setSpotlightRange(const char* lightname, float min_rad, float max_rad)+{+    gMgr->getLight(lightname)->setSpotlightRange(Ogre::Radian(min_rad), Ogre::Radian(max_rad));+}++void newLight(const char* lightname)+{+    gMgr->createLight(lightname);+}++void addLight(const char* lightname, int lighttype, +        float diffcolor_r, float diffcolor_g, float diffcolor_b, +        float speccolor_r, float speccolor_g, float speccolor_b, +        float direction_x, float direction_y, float direction_z,+        float pos_x, float pos_y, float pos_z,+        float range_min_rad, float range_max_rad)+{+    Light::LightTypes type = lighttype == 0 ? Light::LT_POINT : lighttype == 1 ? Light::LT_DIRECTIONAL : Light::LT_SPOTLIGHT;+    Light* light;+    light = gMgr->createLight(lightname);+    light->setType(type);+    light->setDiffuseColour(diffcolor_r, diffcolor_g, diffcolor_b);+    light->setSpecularColour(speccolor_r, speccolor_g, speccolor_b);+    if(type != Light::LT_POINT)+        light->setDirection(direction_x, direction_y, direction_z);+    if(type != Light::LT_DIRECTIONAL)+        light->setPosition(Vector3(pos_x, pos_y, pos_z));+    if(type == Light::LT_SPOTLIGHT)+        light->setSpotlightRange(Ogre::Radian(range_min_rad), Ogre::Radian(range_max_rad));+}++void addPlane(float plane_x, float plane_y, float plane_z, +        float shift, const char *planename, +        float size_x, float size_y, int xseg, int yseg, float utile, float vtile, +        float upvec_x, float upvec_y, float upvec_z, +        float pos_x, float pos_y, float pos_z, +        const char *materialname, int castshadows)+{+    Plane plane (Vector3(plane_x, plane_y, plane_z), shift);+    MeshManager::getSingleton().createPlane(+        "ground", +        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, +        plane, +        size_x, size_y, xseg, yseg, +        true, 1, utile, vtile, Vector3(upvec_x, upvec_y, upvec_z));+    Entity *plent = gMgr->createEntity(planename, "ground");+    SceneNode* plnode = gMgr->getRootSceneNode()->createChildSceneNode();+    plnode->attachObject(plent);+    plnode->setPosition(Vector3(pos_x, pos_y, pos_z));+    plent->setMaterialName(materialname);+    plent->setCastShadows(castshadows);+}++void clearScene()+{+    gMgr->clearScene();+}++void setupCamera(float pos_x, float pos_y, float pos_z, +        float look_x, float look_y, float look_z, +        float roll)+{+    gCam->setPosition (Vector3(pos_x, pos_y, pos_z));+    if(abs(look_x) > epsilon && +       abs(look_y) > epsilon && +       abs(look_z) > epsilon)+        gCam->lookAt(look_x, look_y, look_z);+    if(abs(roll) > epsilon)+        gCam->roll(Radian(roll));+}++void addEntity(const char* name, const char* mesh, +        float pos_x, float pos_y, float pos_z, +        float scale_x, float scale_y, float scale_z, +        float pitch, float yaw, float roll)+{+    std::stringstream nname;+    nname << name << "Node";+    Entity *ent1 = gMgr->createEntity (name, mesh);+    SceneNode *node1 = gMgr->getRootSceneNode()->createChildSceneNode(nname.str());+    node1->setPosition(Vector3(pos_x, pos_y, pos_z));+    node1->setScale(scale_x, scale_y, scale_z);+    node1->yaw(Radian(yaw));+    node1->pitch(Radian(pitch));+    node1->roll(Radian(roll));+    node1->attachObject(ent1);+}++static Node::TransformSpace get_transformspace(int space)+{+    switch (space)+    {+        case 0:+            return Node::TS_LOCAL;+        case 1:+            return Node::TS_PARENT;+        default:+            return Node::TS_WORLD;+    }+}++static void rotateNode(SceneNode* node, float yaw, float pitch, float roll, int space)+{+    Node::TransformSpace ts = get_transformspace(space);+    node->roll(Radian(roll), ts);+    node->yaw(Radian(yaw), ts);+    node->pitch(Radian(pitch), ts);+}++void rotateEntity(const char* name, float yaw, float pitch, float roll, int space)+{+    SceneNode* node = gMgr->getEntity(name)->getParentSceneNode();+    rotateNode(node, yaw, pitch, roll, space);+}++void rotateCamera(float yaw, float pitch, float roll, int space)+{+    gCam->roll(Radian(roll));+    gCam->yaw(Radian(yaw));+    gCam->pitch(Radian(pitch));+}++void translateEntity(const char* name, float x, float y, float z, int space)+{+    SceneNode* node = gMgr->getEntity(name)->getParentSceneNode();+    node->translate(x, y, z, get_transformspace(space));+}++void translateCamera(float x, float y, float z)+{+    gCam->moveRelative(Vector3(x, y, z));+}++void setLightVisible(const char* name, int vis)+{+    gMgr->getLight(name)->setVisible(vis != 0);+}++void setCameraPosition(float x, float y, float z)+{+    gCam->setPosition(Vector3(x, y, z));+}++void getCameraPosition(float* x, float* y, float* z)+{+    const Vector3& v = gCam->getPosition();+    *x = v.x;+    *y = v.y;+    *z = v.z;+}++int raySceneQuerySimple(float orig_x, float orig_y, float orig_z, +                float dir_x, float dir_y, float dir_z,+                float* res_x, float* res_y, float* res_z)+{+    Ray ray(Vector3(orig_x, orig_y, orig_z), Vector3(dir_x, dir_y, dir_z));+    gRaySceneQuery->setRay(ray);++    // Perform the scene query+    RaySceneQueryResult &result = gRaySceneQuery->execute();+    RaySceneQueryResult::iterator itr = result.begin();++    // Get the results+    if (itr != result.end() && itr->worldFragment)+    {+        *res_x = itr->worldFragment->singleIntersection.x;+        *res_y = itr->worldFragment->singleIntersection.y;+        *res_z = itr->worldFragment->singleIntersection.z;+        return 1;+    }+    return 0;+}++int raySceneQueryMouseSimple (float xpos, float ypos, float* res_x, float* res_y, float* res_z)+{+    Ray mouseRay = gCam->getCameraToViewportRay(xpos, ypos);+    gRaySceneQuery->setRay(mouseRay);++    // Execute query+    RaySceneQueryResult &result = gRaySceneQuery->execute();+    RaySceneQueryResult::iterator itr = result.begin();++    // Get the results+    if (itr != result.end() && itr->worldFragment)+    {+        *res_x = itr->worldFragment->singleIntersection.x;+        *res_y = itr->worldFragment->singleIntersection.y;+        *res_z = itr->worldFragment->singleIntersection.z;+        return 1;+    }+    return 0;+}+
+ csrc/ogre_c.h view
@@ -0,0 +1,62 @@+#ifndef __AA_OGRE_H+#define __AA_OGRE_H++#include <OGRE/Ogre.h>+#include <CEGUI/CEGUI.h>+#include <OGRE/OgreCEGUIRenderer.h>++extern "C" +{+int init(int shadow_type, const char* res_filename, int autocreatewindow, const char* title,+        float bg_r, float bg_g, float bg_b, int manager_type);+void setAmbientLight(float ambient_light_r, float ambient_light_g, float ambient_light_b);+int newEntity(const char* name, const char* model, int castshadows);+void setEntityPosition(const char* name, float x, float y, float z);+int cleanup();+int render();+void clearScene();+void addLight(const char* lightname, int lighttype, +        float diffcolor_r, float diffcolor_g, float diffcolor_b, +        float speccolor_r, float speccolor_g, float speccolor_b, +        float direction_x, float direction_y, float direction_z,+        float pos_x, float pos_y, float pos_z,+        float range_min_rad, float range_max_rad);+void addPlane(float plane_x, float plane_y, float plane_z, +        float shift, const char *planename, +        float size_x, float size_y, int xseg, int yseg, float utile, float vtile, +        float upvec_x, float upvec_y, float upvec_z, +        float pos_x, float pos_y, float pos_z, +        const char *materialname, int castshadows);+void setupCamera(float pos_x, float pos_y, float pos_z, +        float look_x, float look_y, float look_z, +        float roll);+void addEntity(const char* name, const char* mesh, +        float pos_x, float pos_y, float pos_z, +        float scale_x, float scale_y, float scale_z, +        float pitch, float yaw, float roll);+int newEntity(const char* name, const char* model, int castshadows);+void setLightType(const char* lightname, int lighttype);+void setLightDiffuseColor(const char* lightname, float color_r, float color_g, float color_b);+void setLightSpecularColor(const char* lightname, float color_r, float color_g, float color_b);+void setLightDirection(const char* lightname, float x, float y, float z);+void setLightPosition(const char* lightname, float x, float y, float z);+void setSpotlightRange(const char* lightname, float min_rad, float max_rad);+void newLight(const char* lightname);+void rotateEntity(const char* name, float yaw, float pitch, float roll, int space);+void rotateCamera(float yaw, float pitch, float roll, int space);+void translateEntity(const char* name, float x, float y, float z, int space);+void translateCamera(float x, float y, float z);+void setLightVisible(const char* name, int vis);+void setSkyDome(int enabled, const char* texture, float curvature);+void setWorldGeometry(const char* cfg);+void setCameraPosition(float x, float y, float z);+void getCameraPosition(float* x, float* y, float* z);+int raySceneQuerySimple(float orig_x, float orig_y, float orig_z, +                float dir_x, float dir_y, float dir_z,+                float* res_x, float* res_y, float* res_z);+int raySceneQueryMouseSimple (float xpos, float ypos, +                float* res_x, float* res_y, float* res_z);+}++#endif+
+ hogre.cabal view
@@ -0,0 +1,31 @@+Name:               hogre+Version:            0.0.1+Cabal-Version:      >= 1.6+License:            OtherLicense+License-File:       LICENSE+Author:             Antti Salonen<ajsalonen at gmail dot com>+Maintainer:         Antti Salonen<ajsalonen at gmail dot com>+Copyright:          Antti Salonen 2009+Stability:          Unstable+Category:           Graphics+Synopsis:           Haskell binding to a subset of OGRE+description:        This package contains bindings to a subset of OGRE+                    (Object-Oriented Graphics Rendering Engine)+                    (<http://www.ogre3d.org/>).+Build-type:         Simple+extra-source-files: csrc/ogre_c.cpp, csrc/ogre_c.h, TODO++source-repository head+  type:      git+  location:  http://github.com/anttisalonen/hogre++Library+  Build-Depends:     base >= 3 && < 5, haskell98+  Hs-Source-Dirs:    src+  Ghc-options:       -Wall+  cc-options:        -Wall+  c-sources:         csrc/ogre_c.cpp+  pkgconfig-depends: OGRE, CEGUI, CEGUI-OGRE+  extra-libraries:   CEGUIOgreRenderer, OgreMain, CEGUIBase+  exposed-modules:   Graphics.Ogre.Ogre+
+ src/Graphics/Ogre/Ogre.hs view
@@ -0,0 +1,430 @@+-- | This module allows simple OGRE usage from Haskell.+--   Note that you need OGRE and CEGUI libraries and headers.+--   Currently, only OGRE version 1.7.0dev-unstable (Cthugha) has been tested.+--   Usage for a simple scene creation:+--+--   1. Define the settings structure 'OgreSettings'.+--+--   2. Define your scene by building up an 'OgreScene'.+--+--   3. call 'initOgre' with your OgreSettings as the parameter.+--+--   4. add your scene using 'addScene'.+--+--   5. Call 'renderOgre' in a loop.+--+--   6. To ensure clean shutdown, call 'cleanupOgre'.+--+{-# LANGUAGE ForeignFunctionInterface #-}+{-# INCLUDE <ogre.h> #-}+module Graphics.Ogre.Ogre(Vector3(..),+        Angle, Rotation(..), Color(..),+        TransformSpace(..),+        ShadowTechnique(..),+        Light(..),+        LightType(..),+        EntityType(..),+        Camera(..),+        Entity(..),+        OgreSettings(..),+        OgreScene(..),+        SceneManagerType(..),+        halfPI,+        degToRad,+        unitX, unitY, unitZ,+        negUnitX, negUnitY, negUnitZ,+        initOgre,+        addScene,+        setupCamera,+        clearScene,+        addLight,+        addEntity,+        setLightPosition,+        setEntityPosition,+        rotateEntity,+        rotateCamera,+        translateEntity,+        translateCamera,+        setLightVisible,+        setAmbientLight,+        setSkyDome,+        setWorldGeometry,+        setCameraPosition,+        getCameraPosition,+        raySceneQuerySimple,+        raySceneQueryMouseSimple,+        renderOgre,+        cleanupOgre)+where++import CTypes+import Foreign.Ptr+import Foreign.Storable+import Foreign.Marshal+import CString++-- C imports+foreign import ccall "ogre.h init" c_init :: CInt -> CString -> CInt -> CString -> CFloat -> CFloat -> CFloat -> CInt -> IO ()+foreign import ccall "ogre.h setAmbientLight" c_set_ambient_light :: CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h setLightPosition" c_set_light_position :: CString -> CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h setEntityPosition" c_set_entity_position :: CString -> CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h cleanup" c_cleanup :: IO ()+foreign import ccall "ogre.h render" c_render :: IO ()+foreign import ccall "ogre.h addEntity" c_add_entity :: CString -> CString -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h setupCamera" c_setup_camera :: CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h addPlane" c_add_plane :: CFloat -> CFloat -> CFloat -> CFloat -> CString -> CFloat -> CFloat -> CInt -> CInt -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CString -> CInt -> IO ()+foreign import ccall "ogre.h addLight" c_add_light :: CString -> CInt -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h rotateEntity" c_rotate_entity :: CString -> CFloat -> CFloat -> CFloat -> CInt -> IO ()+foreign import ccall "ogre.h rotateCamera" c_rotate_camera :: CFloat -> CFloat -> CFloat -> CInt -> IO ()+foreign import ccall "ogre.h translateEntity" c_translate_entity :: CString -> CFloat -> CFloat -> CFloat -> CInt -> IO ()+foreign import ccall "ogre.h translateCamera" c_translate_camera :: CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h setLightVisible" c_set_light_visible :: CString -> CInt -> IO ()+foreign import ccall "ogre.h setSkyDome" c_set_sky_dome :: CInt -> CString -> CFloat -> IO ()+foreign import ccall "ogre.h setWorldGeometry" c_set_world_geometry :: CString -> IO ()+foreign import ccall "ogre.h setCameraPosition" c_set_camera_position :: CFloat -> CFloat -> CFloat -> IO ()+foreign import ccall "ogre.h getCameraPosition" c_get_camera_position :: Ptr CFloat -> Ptr CFloat -> Ptr CFloat -> IO ()+foreign import ccall "ogre.h raySceneQuerySimple" c_ray_scene_query_simple :: +   CFloat -> CFloat -> CFloat -> +   CFloat -> CFloat -> CFloat -> +   Ptr CFloat -> Ptr CFloat -> Ptr CFloat -> IO Int+foreign import ccall "ogre.h raySceneQueryMouseSimple" c_ray_scene_query_mouse_simple :: +   CFloat -> CFloat -> +   Ptr CFloat -> Ptr CFloat -> Ptr CFloat -> IO Int+foreign import ccall "ogre.h clearScene" c_clear_scene :: IO ()++-- Primitive data types+data Vector3 = Vector3 { x :: Float, y :: Float, z :: Float }+    deriving (Eq, Show, Read)++type Angle = Float++data TransformSpace = Local+                    | Parent+                    | World+    deriving (Eq, Show, Read, Enum)++data Rotation = YPR { yaw   :: Angle+                    , pitch :: Angle+                    , roll  :: Angle+                    }+    deriving (Eq, Show, Read)++data Color = Color { r :: Float, g :: Float, b :: Float }+    deriving (Eq, Show, Read)++-- Ogre-specific data types+data ShadowTechnique = None+                     | StencilModulative  -- ^ Note: as of 0.0.1, stencil shadows+                                          -- do not work when the window was created+                                          -- by SDL.+                     | StencilAdditive+                     | TextureModulative+                     | TextureAdditive+                     | TextureAdditiveIntegrated+                     | TextureModulativeIntegrated+    deriving (Eq, Show, Read, Enum)++data Light = Light { lightname :: String+                   , diffuse   :: Color+                   , specular  :: Color+                   , lighttype :: LightType+                   }+    deriving (Eq, Show, Read)++data LightType = PointLight       { plposition  :: Vector3 }+               | DirectionalLight { dldirection :: Vector3 }+               | SpotLight        { slposition  :: Vector3+                                  , sldirection :: Vector3+                                  , range       :: (Angle, Angle)      -- ^ Angle in radians+                                  }+    deriving (Eq, Show, Read)++-- | For Plane parameters, see OGRE documentation at+-- <http://www.ogre3d.org/docs/api/html/classOgre_1_1Plane.html> and +-- Ogre::MeshManager::createPlane: <http://www.ogre3d.org/docs/api/html/classOgre_1_1MeshManager.html>+data EntityType = StdMesh { mesh        :: String +                          , rotation    :: Rotation+                          }+                | Plane { normal      :: Vector3+                        , shift       :: Float+                        , width       :: Float+                        , height      :: Float+                        , xsegments   :: Int+                        , ysegments   :: Int+                        , utile       :: Float+                        , vtile       :: Float+                        , upvector    :: Vector3+                        , material    :: String+                        }+    deriving (Eq, Show, Read)++data Camera = Camera { lookat      :: Vector3+                     , camroll     :: Angle+                     , camposition :: Vector3+                     }+    deriving (Eq, Show, Read)++defaultCamera :: Camera+defaultCamera = Camera (Vector3 1.0 0.0 0.0) 0 (Vector3 0.0 0.0 0.0)++data Entity = Entity { name        :: String      -- ^ Unique identifier for the +                                                  --   entity.+                     , position    :: Vector3+                     , entitytype  :: EntityType  -- ^ EntityType is usually a mesh.+                     , castshadows :: Bool+                     , scale       :: Vector3+                     }+    deriving (Eq, Show, Read)++data SceneManagerType = Generic+                      | ExteriorClose+                      | ExteriorFar+                      | ExteriorRealFar+                      | Interior+    deriving (Eq, Show, Read)++-- Main Ogre data types+-- | General, scene-wide Ogre settings. Main configuration structure for Ogre.+data OgreSettings = OgreSettings { resourcefile     :: FilePath          -- ^ Path to resources.cfg.+                                 , autocreatewindow :: Bool              -- ^ Whether the window should +                                                                         -- be created automatically (by Ogre).+                                                                         -- Turn this off if the window should+                                                                         -- be created by another library+                                                                         -- (e.g.) SDL.+                                 , caption          :: String            -- ^ Window caption.+                                 , ambientlight     :: Color+                                 , shadowtechnique  :: ShadowTechnique+                                 , scenemanagertype :: [SceneManagerType] -- ^ Flags for the scene manager.+                                                                          --   Most scenes only need to set +                                                                          --   Generic as type.+                                 }+    deriving (Eq, Show, Read)++-- | Entities and other objects that define the scene.+data OgreScene = OgreScene { camera          :: Camera+                           , entities        :: [Entity]+                           , lights          :: [Light]+                           }+    deriving (Eq, Show, Read)++-- Helpers+halfPI :: Float+halfPI = pi * 0.5++degToRad :: Float -> Float+degToRad d = d * pi / 180.0++unitX :: Vector3+unitX = Vector3 1.0 0.0 0.0++unitY :: Vector3+unitY = Vector3 0.0 1.0 0.0++unitZ :: Vector3+unitZ = Vector3 0.0 0.0 1.0++nullVector :: Vector3+nullVector = Vector3 0.0 0.0 0.0++negUnitX :: Vector3+negUnitX = Vector3 (-1.0) 0.0 0.0++negUnitY :: Vector3+negUnitY = Vector3 0.0 (-1.0) 0.0++negUnitZ :: Vector3+negUnitZ = Vector3 0.0 0.0 (-1.0)++managerMaskFromEnum :: [SceneManagerType] -> CInt+managerMaskFromEnum = foldl go 0+    where go acc s = acc + go' s+          go' Generic          = 1+          go' ExteriorClose    = 2+          go' ExteriorFar      = 4+          go' ExteriorRealFar  = 8+          go' Interior         = 16++-- | Initializes Ogre with given settings. This must be called before manipulating or rendering the scene.+initOgre :: OgreSettings -> IO ()+initOgre sett = do+    let mgr_type = max 1 (managerMaskFromEnum (scenemanagertype sett))+    withCString (resourcefile sett) $ \c_res -> do+    withCString (caption sett) $ \c_caption -> do+    c_init ((fromIntegral . fromEnum) (shadowtechnique sett)) c_res ((fromIntegral . fromEnum) (autocreatewindow sett)) c_caption 0.0 0.0 0.0 mgr_type+    setAmbientLight (ambientlight sett)+    setupCamera defaultCamera++setAmbientLight :: Color -> IO ()+setAmbientLight (Color r_ g_ b_) = c_set_ambient_light (realToFrac r_) (realToFrac g_) (realToFrac b_)++clearScene :: IO ()+clearScene = c_clear_scene++addScene :: OgreScene -> IO ()+addScene scen = do+    setupCamera (camera scen)+    mapM_ addLight (lights scen)+    mapM_ addEntity (entities scen)++setupCamera :: Camera -> IO ()+setupCamera (Camera look rol pos) = do+    c_setup_camera +        (realToFrac (x pos)) +        (realToFrac (y pos)) +        (realToFrac (z pos)) +        (realToFrac (x look)) +        (realToFrac (y look)) +        (realToFrac (z look)) +        (realToFrac rol)++addLight :: Light -> IO ()+addLight (Light nam dif spec ltype) = do+    let (t, pos, dir, rmin, rmax) = case ltype of+          PointLight       lp                 -> (0, lp, nullVector, 0, 0)+          DirectionalLight ld                 -> (1, nullVector, ld, 0, 0)+          SpotLight        lp ld (lrmi, lrma) -> (2, lp, ld, lrmi, lrma)+    withCString nam $ \c_name -> do+      c_add_light c_name t+        (realToFrac (r dif)) +        (realToFrac (g dif)) +        (realToFrac (b dif)) +        (realToFrac (r spec)) +        (realToFrac (g spec)) +        (realToFrac (b spec)) +        (realToFrac (x dir)) +        (realToFrac (y dir)) +        (realToFrac (z dir)) +        (realToFrac (x pos)) +        (realToFrac (y pos)) +        (realToFrac (z pos)) +        (realToFrac rmin) +        (realToFrac rmax)++addEntity :: Entity -> IO ()+addEntity (Entity n pos t sh sc) = do+    withCString n $ \c_name -> do+    case t of+      StdMesh m (YPR ya pit ro) -> do+        withCString m $ \c_meshname -> do+        c_add_entity c_name c_meshname +                (realToFrac (x pos)) +                (realToFrac (y pos)) +                (realToFrac (z pos)) +                (realToFrac (x sc)) +                (realToFrac (y sc)) +                (realToFrac (z sc)) +                (realToFrac pit) (realToFrac ya) (realToFrac ro)+      Plane norm shif wid hei xseg yseg ut vt upv mat -> do+        withCString mat $ \c_material -> do+        c_add_plane (realToFrac (x norm)) (realToFrac (y norm)) (realToFrac (z norm)) (realToFrac (shif)) c_name (realToFrac (wid)) (realToFrac (hei)) (fromIntegral xseg) (fromIntegral (yseg)) (realToFrac (ut)) (realToFrac (vt)) (realToFrac (x upv)) (realToFrac (y upv)) (realToFrac (z upv)) (realToFrac (x pos)) (realToFrac (y pos)) (realToFrac (z pos)) c_material ((fromIntegral . fromEnum) sh)++setLightPosition :: String    -- ^ Name of light+                 -> Vector3   -- ^ New position+                 -> IO ()+setLightPosition n (Vector3 x_ y_ z_) = withCString n $ \cn -> c_set_light_position cn (realToFrac x_) (realToFrac y_) (realToFrac z_)++setEntityPosition :: String    -- ^ Name of entity+                  -> Vector3   -- ^ New position+                  -> IO ()+setEntityPosition n (Vector3 x_ y_ z_) = withCString n $ \cn -> c_set_entity_position cn (realToFrac x_) (realToFrac y_) (realToFrac z_)++rotateEntity :: String -> Rotation -> TransformSpace -> IO ()+rotateEntity n (YPR ya pit ro) ts = withCString n $ \cn -> c_rotate_entity cn (realToFrac ya) (realToFrac pit) (realToFrac ro) ((fromIntegral . fromEnum) ts)++rotateCamera :: Rotation -> TransformSpace -> IO ()+rotateCamera (YPR ya pit ro) ts = c_rotate_camera (realToFrac ya) (realToFrac pit) (realToFrac ro) ((fromIntegral . fromEnum) ts)++translateEntity :: String -> Vector3 -> TransformSpace -> IO ()+translateEntity n (Vector3 x_ y_ z_) ts = withCString n $ \cn -> c_translate_entity cn (realToFrac x_) (realToFrac y_) (realToFrac z_) ((fromIntegral . fromEnum) ts)++translateCamera :: Vector3 -> IO ()+translateCamera (Vector3 x_ y_ z_) = c_translate_camera (realToFrac x_) (realToFrac y_) (realToFrac z_)++setLightVisible :: String -> Bool -> IO ()+setLightVisible n v = withCString n $ \cn -> c_set_light_visible cn ((fromIntegral . fromEnum) v)++-- | See Ogre::SceneManager::setSkyDome().+setSkyDome :: Maybe (String, Float) -- ^ If Nothing, will disable sky dome. +                                    -- Otherwise, String refers to the +                                    -- material name. Float defines the+                                    -- curvature. +           -> IO ()+setSkyDome Nothing = withCString "" $ \cs -> c_set_sky_dome 0 cs 5+setSkyDome (Just (n, curv)) = withCString n $ \cs -> c_set_sky_dome 1 cs (realToFrac curv)++-- | See Ogre::SceneManager::setWorldGeometry().+setWorldGeometry :: String -> IO ()+setWorldGeometry s = withCString s $ \cs -> c_set_world_geometry cs++setCameraPosition :: Vector3 -> IO ()+setCameraPosition v = withCVector v c_set_camera_position++getCameraPosition :: IO Vector3+getCameraPosition = alloca $ \x_ -> do+                    alloca $ \y_ -> do+                    alloca $ \z_ -> do+                    c_get_camera_position x_ y_ z_+                    xx <- peek x_+                    yy <- peek y_+                    zz <- peek z_+                    return (Vector3 (realToFrac xx) (realToFrac yy) (realToFrac zz))++withCVector :: Vector3 -> (CFloat -> CFloat -> CFloat -> IO a) -> IO a+withCVector (Vector3 xx yy zz) f = do+    let x_ = realToFrac xx+    let y_ = realToFrac yy+    let z_ = realToFrac zz+    f x_ y_ z_++fromCVector :: CFloat -> CFloat -> CFloat -> Vector3+fromCVector x_ y_ z_ = Vector3 (realToFrac x_) (realToFrac y_) (realToFrac z_)++-- | Creates a ray scene query.+raySceneQuerySimple :: Vector3 -- ^ Origin of ray+                    -> Vector3 -- ^ Direction of ray+                    -> IO (Maybe Vector3) -- ^ Point where ray intersects +                                          --   something, or Nothing if not found+raySceneQuerySimple orig dir = +    alloca $ \resx -> do+    alloca $ \resy -> do+    alloca $ \resz -> do+    withCVector orig $ \ox oy oz -> do+    withCVector dir $ \dx dy dz  -> do+    found <- c_ray_scene_query_simple ox oy oz dx dy dz resx resy resz+    if found == 0+      then return Nothing+      else do+             xx <- peek resx+             yy <- peek resy+             zz <- peek resz+             return (Just (fromCVector xx yy zz))++-- | Creates a ray scene query based on given mouse coordinates.+raySceneQueryMouseSimple :: Float -- ^ X-coordinate (width) of the ray origin+                                  --   on screen, between 0 (left) +                                  --   and 1 (right).+                         -> Float -- ^ Y-coordinate (height) of the ray origin+                                  --   on screen, between 0 (top)+                                  --   and 1 (bottom).+                         -> IO (Maybe Vector3) -- ^ Point where ray intersects+                                               --   something, or Nothing if not found+raySceneQueryMouseSimple xpos ypos = +    alloca $ \resx -> do+    alloca $ \resy -> do+    alloca $ \resz -> do+    found <- c_ray_scene_query_mouse_simple (realToFrac xpos) (realToFrac ypos) resx resy resz+    if found == 0+      then return Nothing+      else do+             xx <- peek resx+             yy <- peek resy+             zz <- peek resz+             return (Just (fromCVector xx yy zz))++-- | 'renderOgre' renders one frame.+renderOgre :: IO ()+renderOgre = c_render++cleanupOgre :: IO ()+cleanupOgre = c_cleanup+