This is an example of how to use the Nebula engine as a back-end renderer. Nebula could probably be easily interfaced with WorldFoundry in this way to use Nebula's powerful rendering capabilities.

Original source: http://nebuladevice.sourceforge.net/cgi-bin/twiki/view/Nebula/BoxBallDemo

Notes:

  • the code inside while (gfx->Trigger() && running) does the rendering. This needs to be put inside the WorldFoundry main loop.
  • The statement graph->Attach(root, 0); attaches the entire visual hierarchy (the root node) to the scenegraph, which is then rendered by Nebula by triggering the gfx server (this is why gfx->Trigger() is the while loop condition). Instead of attaching the entire visual hierarchy, WorldFoundry would attach only those visual nodes for those parts of the scene to be rendered - in the previous, current, and next rooms. Here it is clear how Nebula is carefully designed not to dictate any policy, so it can work with any visibility system.
  • WorldFoundry needs to generate visual hierarchy nodes (probably at level load time) to send to Nebula; i.e. there needs to be a "parallel" database of Nebula visual objects, and WF merely decides which of these objects get drawn at which point in time. See InterfacingNebulaDeviceAndWorldFoundry

// This software is provided 'as-is', without any express or implied warranty. In no event will
// Nebula or the author be held liable for any damages arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose, including commercial
// applications, and to alter it and redistribute it freely.  Technical support is not offered by
// Nebula or the author for this program.  All I ask is that you send any modifications, big or
// small, you want to share to ddurocher@rica.net along with a full description as to what was
// changed or added so I can keep this tutorial/demo updated.
//-------------------------------------------------------------------
// This tutorial/demo is a scalped Gfxserv.cc for loading scripts (*.n and *.tcl).  It's a very
// basic example of what can be done using Nebula.  The objects were made in Lightwave and
// exported using Ilya Kliot's LWS to TND exporter.
//-------------------------------------------------------------------
// DESCRIPTION:
// A rotating textured ball moves from left to right while a rotating textured box does a figure
// 8 around it.
//-------------------------------------------------------------------

// All headers, classes, etc are located here.
#include "load_scripts.h"

int main(int argc, char *argv[])
{
    char *port_name = "gfxserv";
    char *server_class = "nglserver";
    char *mode = "w(512)-h(512)";
    char *script_server = "ntclserver";
    bool grid = true;
    bool nosleep = false;
    const char* result;

    // hier geht's los
    V.ident();
    vector3 t(0.0f,2.5f,0.0f);
    V.translate(t);

    // Start a new Kernel Server.
    nKernelServer* ks       = new nKernelServer;

    // Startup the basic servers
    nFileServer2* fs2       = (nFileServer2*)       ks->New("nfileserver2",         "/sys/servers/file2");
    nGfxServer* gfx         = (nGfxServer *)        ks->New(server_class,           "/sys/servers/gfx");
    nInputServer* inp       = (nInputServer *)      ks->New("ninputserver",         "/sys/servers/input");
    nTclServer* script      = (nTclServer *)        ks->New(script_server,          "/sys/servers/script");
    nSceneGraph2* graph     = (nSceneGraph2 *)      ks->New("nscenegraph2",         "/sys/servers/sgraph2");
    nShadowServer* shadow   = (nShadowServer *)     ks->New("nsbufshadowserver",    "/sys/servers/shadow");
    nChannelServer* chn     = (nChannelServer*)     ks->New("nchannelserver",       "/sys/servers/channel");
    nConServer *con         = (nConServer *)        ks->New("nconserver",           "/sys/servers/console");
    nMathServer *math       = (nMathServer *)       ks->New("nmathserver",          "/sys/servers/math");
    nParticleServer *part   = (nParticleServer *)   ks->New("nparticleserver",      "/sys/servers/particle");
    nSpecialFxServer *fx    = (nSpecialFxServer *)  ks->New("nspecialfxserver",     "/sys/servers/specialfx");
    n3DNode *root           = (n3DNode *)           ks->New("n3dnode",              "/usr/scene");

    // Open Box
    // RunScript = evaluate a script file.
    // Lookup = Look up a path and return the corresponding nRoot object.
    script->RunScript("..\\load_scripts\\box\\box.n",result);
    box = (n3DNode*) ks->Lookup("/load_scripts/box");

    // Open Ball
    // RunScript = evaluate a script file.
    // Lookup = Look up a path and return the corresponding nRoot object.
    script->RunScript("..\\load_scripts\\ball\\ball.n",result);
    ball = (n3DNode*) ks->Lookup("/load_scripts/ball");

    // Define a new display mode. The new display mode will not show up until the
    // display is actually (re-)opened via CloseDisplay()/OpenDisplay().
    gfx->SetDisplayMode(mode);

    //Open the display as defined by SetDisplayMode(). This will restore the app
    //window and create a new d3d device.
    gfx->OpenDisplay();

    // If 'running' is set to false, the nGlServer Window will open then close
    // automatically
    bool running = true;
    // Boolean Trigger() (true/false). If '&& running' is set to "&& !running", a
    // LINK:fatal error LNK1168 will occur
    while (gfx->Trigger() && running)
      {
         if (!script->Trigger()) running = false;
         ks->Trigger();
            ks->ts->Trigger();
         //  The purpose of GetFrameTime() is to get an exactly identical
         //  frame-timestamp within two nTimeServer::Trigger() calls
         //  (whereas a nTimeServer::GetTime() will return a different
         //  timestamp each time it is called).
         double t = ks->ts->GetFrameTime();
         inp->Trigger(t);

         // Begin keyboard and mouse Input-Messages.
         nInputEvent *ie;
         // Go to the first input event
         if ((ie = inp->FirstEvent()))
            {
                // Has a keyboard or mouse key been pressed? handleInput() is a user
                // function
                do handleInput(con,ie); while ((ie = inp->NextEvent(ie)));
                inp->FlushEvents();
            }

            // Speed at which the screen moves when the keyboard or mouse keys are
            // pressed.  handleViewer() is a user made function.
            handleViewer();

            // Render Scene
            if (gfx->BeginScene())
                {
                    nRState rs;
                    matrix44 vwr;
                    vwr = V;
                    // inverts a 4x4 matrix consisting of a 3x3 rotation matrix and a
                    // translation (eg. everything that has [0,0,0,1] as the rightmost
                    // column) MUCH cheaper then a real 4x4 inversion.
                    vwr.invert_simple();

                    // trigger particle server
                    part->Trigger();

                    // Viewer-Matrix setzen
                    gfx->SetMatrix(N_MXM_VIEWER,V);

                    // Scenegraph vollrendern
                    chn->SetChannel1f(chn->GenChannel("time"), (float) t);
                    chn->SetChannel1f(chn->GenChannel("gtime"), (float) t);

               // Begin the scene
               if (graph->BeginScene(vwr))
                    {
                        fx->Begin();
                        // attach a visnode hierarchy to the scene.
                        graph->Attach(root, 0);
                        // GlEnd() - Not sure what this does.
                        fx->End(graph);
                        // end the scene.
                        graph->EndScene(true);
                    }

               /* Render the grid on the screen with a blue background */
                if (grid) {
                    rs.Set(N_RS_TEXTUREHANDLE,0);  gfx->SetState(rs);
                    rs.Set(N_RS_LIGHTING,N_FALSE); gfx->SetState(rs);
                    // Set one of the modelview or projection matrices.
                    gfx->SetMatrix(N_MXM_MODELVIEW,vwr);
                    gfx->Begin(N_PTYPE_LINE_LIST);
                    // Set the background color here.
                    gfx->Rgba(0.1f,0.5f,2.0f,1.0f);
                    // Set the size of the grid here.
                    float p;
                        for (p=-25.0f; p<=+25.0f; p+=1.0f)
                            {
                               gfx->Coord(p, 0.0f, -25.0f);
                               gfx->Coord(p, 0.0f, +25.0f);
                               gfx->Coord(-25.0f, 0.0f, p);
                               gfx->Coord(+25.0f, 0.0f, p);
                            }
                    // End Gfxserver
                    gfx->End();
                    rs.Set(N_RS_LIGHTING,N_TRUE); gfx->SetState(rs);
                }
                /* End grid render */

               // End this scene
               gfx->EndScene();
                }
            }
    // Close the display open by OpenDisplay(). This will minimize the app window and destroy
    // the d3d device.
    gfx->CloseDisplay();

    if (root)   root->Release();
    if (part)   part->Release();
    if (math)   math->Release();
    if (con)    con->Release();
    if (chn)    chn->Release();
    if (shadow) shadow->Release();
    if (graph)  graph->Release();
    if (script) script->Release();
    if (gfx)    gfx->Release();
    if (inp)    inp->Release();
    if (fs2)    fs2->Release();

    if (load_scripts)   load_scripts->Release();
    if (box)            box->Release();
    if (ball)            ball->Release();

    delete ks;
    return 0;
}
Topic revision: r2 - 03 Sep 2009, WillNorris
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Foswiki? Send feedback