[BACK] Return to main.cpp CVS log [TXT][DIR] Up to Nevrax / code / nel / samples / pacs

File: Nevrax / code / nel / samples / pacs / main.cpp (download)
Revision 1.2, Wed Feb 20 18:07:14 2002 UTC (5 months ago) by lecroart
Branch: MAIN
CVS Tags: georges_v2, HEAD
Changes since 1.1: +2 -2 lines
#FIXED: doxygen warning

/** \file pacs/main.cpp
 * Pacs sample using user interface.
 *
 * $Id: main.cpp,v 1.2 2002/02/20 18:07:14 lecroart Exp $
 */

/* Copyright, 2001 Nevrax Ltd.
 *
 * This file is part of NEVRAX NEL.
 * NEVRAX NEL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.

 * NEVRAX NEL is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with NEVRAX NEL; see the file COPYING. If not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#include "object.h"

// Pacs includes
#include <nel/pacs/u_move_container.h>
#include <nel/pacs/u_move_primitive.h>
#include <nel/pacs/u_collision_desc.h>

// Misc includes
#include <nel/misc/time_nl.h>
#include <nel/misc/path.h>

// 3d includes
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/u_text_context.h>
#include <nel/3d/u_instance.h>
#include <nel/3d/u_scene.h>
#include <nel/3d/u_3d_mouse_listener.h>
#include <nel/3d/u_material.h>

#ifdef NL_OS_WINDOWS

// Just for the main function and ::MessageBox
#include <windows.h>

#endif // NL_OS_WINDOWS

using namespace NLMISC;
using namespace NL3D;
using namespace NLPACS;

// Some defines
#define ARENA_SIZE 50
#define NUM_CELL 10

#define SIZE_PRIMITIVE_MIN (1)
#define SIZE_PRIMITIVE_MAX 2
#define KEYBOARD_ACCEL (5.0)    // m.s-2
#define SHOCK_ABSORB (0.9)              //
#define DELTA_TIME (0.1)
#define GO (10)
#define BORDER_SIZE SIZE_PRIMITIVE_MAX
#define INIT_SPEED 9
#define MAX_WORLD_IMAGE 31

volatile bool synchro;

// Get a random size
double randomSize ()
{
        return (SIZE_PRIMITIVE_MAX - SIZE_PRIMITIVE_MIN)*((double)rand() / (double)RAND_MAX) + SIZE_PRIMITIVE_MIN;
}

// Get a random rotation
double randomRot ()
{
        return 2*(double)Pi*((double)rand() / (double)RAND_MAX);
}

// Get a random speed
CVectorD randomSpeed ()
{
        return CVectorD (        2*(double)INIT_SPEED*((double)rand() / (double)RAND_MAX) - INIT_SPEED,
                                                2*(double)INIT_SPEED*((double)rand() / (double)RAND_MAX) - INIT_SPEED, 0);
}

// Get a random pos
CVectorD randomPos ()
{
        return CVectorD (        ((double)ARENA_SIZE - 2*BORDER_SIZE - SIZE_PRIMITIVE_MAX)*((double)rand() / (double)RAND_MAX) - ARENA_SIZE / 2.0 + BORDER_SIZE+ (SIZE_PRIMITIVE_MAX) / 2,
                                                ((double)ARENA_SIZE - 2*BORDER_SIZE - SIZE_PRIMITIVE_MAX)*((double)rand() / (double)RAND_MAX) - ARENA_SIZE / 2.0 + BORDER_SIZE+ (SIZE_PRIMITIVE_MAX) / 2,
                                                0);
}

// Setup speed with keyboard
void keyboard (UDriver  *pDriver, double deltaTime, CObjectDyn &obj)
{
        // Add speed to selected object
        CVectorD speed (0,0,0);
        if (pDriver->AsyncListener.isKeyDown (KeyLEFT))
                speed.x+=KEYBOARD_ACCEL*deltaTime;
        if (pDriver->AsyncListener.isKeyDown (KeyRIGHT))
                speed.x-=KEYBOARD_ACCEL*deltaTime;
        if (pDriver->AsyncListener.isKeyDown (KeyUP))
                speed.y-=KEYBOARD_ACCEL*deltaTime;
        if (pDriver->AsyncListener.isKeyDown (KeyDOWN))
                speed.y+=KEYBOARD_ACCEL*deltaTime;
        if (pDriver->AsyncListener.isKeyDown (KeyPRIOR))
                speed.z+=KEYBOARD_ACCEL*deltaTime;
        if (pDriver->AsyncListener.isKeyDown (KeyNEXT))
                speed.z-=KEYBOARD_ACCEL*deltaTime;

        // Set new speed
        if (speed.norm() > 0)
                obj.setSpeed(obj.getSpeed ()+speed);
}

// ** Main entry

#ifdef NL_OS_WINDOWS

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)

#else // NL_OS_WINDOWS

int main ()

#endif // NL_OS_WINDOWS

{
        try
        {
                // Init search pathes
                CPath::addSearchPath ("shapes");
                
                // Create a driver
                UDriver        *pDriver=UDriver::createDriver();

                // Setup text context
                pDriver->setDisplay (UDriver::CMode(640, 480, 0));

                // Create a scene
                UScene *pScene=pDriver->createScene();

                // Create a container
                // This container has 31 world images. The first is a static world image, the others are dynamic.
                // Each frame, the sample eval the collision in the next dynamic world image.
                // This is to show the multiple world images fonctionnality.
                UMoveContainer *container=UMoveContainer::createMoveContainer (-ARENA_SIZE/2.0, -ARENA_SIZE/2.0, ARENA_SIZE/2.0, ARENA_SIZE/2.0,
                        NUM_CELL, NUM_CELL, (double)SIZE_PRIMITIVE_MAX*sqrt(2.0), MAX_WORLD_IMAGE );

                // Set the world image 0 as static (for borders)
                container->setAsStatic (0);

                // Array arena
                std::vector<CObjectDyn*>        arrayArena;

                // Create an arena with boxes
                int num_cell=ARENA_SIZE/SIZE_PRIMITIVE_MAX+1;
                for (int cell=0; cell<num_cell; cell++)
                {
                        // Create static boxes around the test area
                        arrayArena.push_back (new CObjectDyn (SIZE_PRIMITIVE_MAX, SIZE_PRIMITIVE_MAX, 10*SIZE_PRIMITIVE_MAX, 0, 
                                CVectorD (SIZE_PRIMITIVE_MAX*cell-(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, (ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, 0),
                                CVectorD(0,0,0), true, *container, *pScene, UMovePrimitive::DoNothing, 0, 1, 0));
                        arrayArena.push_back (new CObjectDyn (SIZE_PRIMITIVE_MAX, SIZE_PRIMITIVE_MAX, 10*SIZE_PRIMITIVE_MAX, 0, 
                                CVectorD (SIZE_PRIMITIVE_MAX*cell-(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, -(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, 0),
                                CVectorD(0,0,0), true, *container, *pScene, UMovePrimitive::DoNothing, 0, 1, 0));
                        arrayArena.push_back (new CObjectDyn (SIZE_PRIMITIVE_MAX, SIZE_PRIMITIVE_MAX, 10*SIZE_PRIMITIVE_MAX, 0, 
                                CVectorD ((ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, SIZE_PRIMITIVE_MAX*cell-(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, 0),
                                CVectorD(0,0,0), true, *container, *pScene, UMovePrimitive::DoNothing, 0, 1, 0));
                        arrayArena.push_back (new CObjectDyn (SIZE_PRIMITIVE_MAX, SIZE_PRIMITIVE_MAX, 10*SIZE_PRIMITIVE_MAX, 0, 
                                CVectorD (-(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, SIZE_PRIMITIVE_MAX*cell-(ARENA_SIZE-SIZE_PRIMITIVE_MAX)/2, 0),
                                CVectorD(0,0,0), true, *container, *pScene, UMovePrimitive::DoNothing, 0, 1, 0));
                }

                // Setup camera
                UCamera        *pCam=pScene->getCam();
                pCam->setTransformMode (UTransformable::DirectMatrix);
                pCam->setPerspective ((float)Pi/2.f, 1.33f, 0.1f, 1000);

                // Setup the mouse listener
                U3dMouseListener *plistener=pDriver->create3dMouseListener ();
                plistener->setHotSpot (CVectorD (0,0,0));
                plistener->setFrustrum (pCam->getFrustum());
                plistener->setMatrix (pCam->getMatrix());
                plistener->setMouseMode (U3dMouseListener::edit3d);

                // Array of dynamic objects
                std::vector<CObjectDyn*>        arrayObj;

                // Create one object
                arrayObj.push_back (
                        new CObjectDyn (randomSize (), randomSize (), randomPos (), CVectorD(0,0,0), true, *container, *pScene, 
                                UMovePrimitive::Reflexion, 1, 30, 1));

                // Selected object
                uint selected=0;

                // Get time
                TTime lastTime=CTime::getLocalTime ();

                // Current world image
                uint worldImage=1;

                // Color to clear the background
                CRGBA clearColor;

                // Main loop
                while (pDriver->isActive() && (!pDriver->AsyncListener.isKeyPushed (KeyESCAPE)))
                {
                        // Get the current time
                        TTime newTime=CTime::getLocalTime ();
                        double deltaTime=(double)(uint32)(newTime-lastTime)/1000.0;
                        lastTime=newTime;

                        // Insert objects in press INSERT
                        if (pDriver->AsyncListener.isKeyDown (KeyINSERT))
                        {
                                // Random cylinder and boxes
                                if (rand()&1)
                                        arrayObj.push_back (new CObjectDyn (randomSize(), randomSize(), randomSize(), randomRot(), randomPos (), CVectorD(0,0,0), 
                                        true, *container, *pScene, UMovePrimitive::Reflexion, 1, 30, worldImage));
                                else
                                        arrayObj.push_back (new CObjectDyn (randomSize (), randomSize (), randomPos (), CVectorD(0,0,0), true, *container, 
                                        *pScene, UMovePrimitive::Reflexion, 1, 30, worldImage));
                        }

                        // Make caos if SPACE pressed
                        if (pDriver->AsyncListener.isKeyDown (KeySPACE))
                        {
                                for (uint t=0; t<arrayObj.size(); t++)
                                        arrayObj[t]->setSpeed (randomSpeed ());
                        }

                        // Keyboard
                        if (arrayObj.size())
                        {
                                // Manipulate selected primitive
                                keyboard (pDriver, deltaTime, *(arrayObj[selected]));

                                // Remove a primitive if DELETE pressed
                                if (pDriver->AsyncListener.isKeyDown (KeyDELETE))
                                {
                                        arrayObj[arrayObj.size()-1]->remove (*container, *pScene);
                                        arrayObj.resize (arrayObj.size()-1);
                                }

                                // Check selected
                                if (selected>=arrayObj.size())
                                        selected=arrayObj.size()-1;
                                if (selected<0)
                                        selected=0;

                                // Change selected object if TAB pressed
                                if (pDriver->AsyncListener.isKeyPushed (KeyTAB))
                                {
                                        selected++;
                                        selected%=arrayObj.size();
                                }
                        }

                        // Move primitives
                        for (uint i=0; i<arrayObj.size(); i++)
                                arrayObj[i]->tryMove (DELTA_TIME, *container, worldImage);

                        // Eval static world image
                        container->evalCollision (DELTA_TIME, 0);

                        // Eval current dynamic world image
                        container->evalCollision (DELTA_TIME, worldImage);
                        
                        // Simulation new position
                        for (i=0; i<arrayObj.size(); i++)
                                arrayObj[i]->doMove (DELTA_TIME, worldImage);

                        // Check triggers
                        clearColor=CRGBA::Black;
                        if (container->getNumTriggerInfo())
                        {
                                // White if collision
                                clearColor=CRGBA (100,100,100);
                        }

                        // Setup view matrix
                        int size=arrayObj.size();
                        if (size)
                        {
                                // Setup hotspot for the 3d listener
                                plistener->setHotSpot (arrayObj[selected]->getPos());

                                // Look at selected primitive
                                pCam->lookAt (plistener->getViewMatrix().getPos (), arrayObj[selected]->getPos());
                        }

                        // Force listener current matrix
                        plistener->setMatrix (pCam->getMatrix());

                        // Clear
                        pDriver->clearBuffers (clearColor);

                        // Render
                        pScene->render ();

                        // Draw some lines
                        pDriver->setMatrixMode3D(*pCam);

                        // Swap
                        pDriver->swapBuffers ();

                        // Pump messages
                        pDriver->EventServer.pump();

                        // Next world image
                        int nextImage=worldImage+1;
                        if (nextImage>=MAX_WORLD_IMAGE)
                                nextImage=1;
                        container->duplicateWorldImage (worldImage, nextImage);
                        worldImage=nextImage;
                }

                // Remove mouse listener
                pDriver->delete3dMouseListener (plistener);
        }
        catch (Exception& e)
        {
#ifdef NL_OS_WINDOWS
                ::MessageBox (NULL, e.what(), "Test collision move", MB_OK|MB_ICONEXCLAMATION);
#else // NL_OS_WINDOWS
                printf (e.what());
#endif // NL_OS_WINDOWS
        }

        return 0;
}