Creando Geometría

De CursosGpl

creando geometría
creando geometría

tercera parte del tutorial

En este capítulo creamos algo de geometría directamente en el código.

código c++

Tabla de contenidos

[editar] Conceptos

[editar] Los eventos de dibujado

Una vez que hemos entrado en el bucle principal de CrystalSpace este toma control y va pasando eventos a nuestra función de gestión de eventos como vimos en el capítulo anterior.

CrystalSpace nos pasa ciertos eventos para indicarnos cuando iniciar o terminar el dibujado. Estos son cscmdProcess y cscmdFinalProcess.

Estos eventos se detectan de la siguiente manera:

ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess
ev.Type == csevBroadcast && ev.Command.Code == cscmdFinalProcess 

Hay algunos eventos más relativos a la preparación y dibujado de un cuadro pero no se ven aquí.

Debemos responder a ellos con el código necesario para comenzar el renderizado y el necesario para terminar.

Antes de dibujar debemos indicar que vamos a dibujar formas 3D.

// Indicarle al driver 3d que vamos a dibujar formas tridimensionales
 if (!g3d->BeginDraw(
   engine->GetBeginDrawFlags() | CSDRAW_3DGRAPHICS))
   return;
 // Le decimos a la cámara que dibuje en el frame buffer
 view->Draw ();

Normalmente este código va al final de la función de respuesta al evento cscmdProcess, antes deberemos incluir el código necesario para preparar el cuadro.

Al recibir el evento cscmdFinalProcess:

g3d->FinishDraw ();

[editar] Creación de geometría

Para crear toda la geometría necesaria para una pequeña habitación hay que dar varios pasos.

[editar] Crear una textura

Cargamos la textura usando el cargador de objetos de crystalspace.

loader->LoadTexture ("stone", "/lib/std/stone4.gif")

[editar] Crear un sector

Antes de definir la geometría debemos crear un sector. Un sector es una zona del mundo independiente de otros sectores. Sirven para ayudar al motor a discriminar qué partes del mundo renderizar y para crear geometrías imposibles.

Los sectores se conectan entre sí utilizando portales, pero en este ejemplo no nos hacen falta ya que solo crearemos un sector.

El sector se crea utilizando el motor directamente y responde al interfaz iSector.

csRef<iSector> habitacion;
habitacion = engine->CreateSector ("room");

[editar] Crear los Muros

Una vez que tenemos el sector creamos un cubo a través de un objeto de tipo thing.

csRef<iMeshWrapper> muros;
muros = engine->CreateSectorWallsMesh (room, "walls") 

[editar] Incluir luces

Finalmente añadimos algunas luces para poder ver algo. Las luces responden al interfaz iLight.

csRef<iLight> luz;
luz = engine->CreateLight (0, csVector3 (-3, 5, 0), 10, csColor (1, 0, 0));

Y las añadimos al sector

habitacion->GetLights()->Add(luz)

[editar] Inicialización de la cámara

[editar] Programación

[editar] Respuesta a eventos

A CrystalSpace le tenemos que pasar una función con direccionamiento estático, es decir que si queremos que esté dentro de una clase tiene que ser del tipo static, por lo tanto creamos dos funciones una estática y la otra no y llamamos desde la primera a la segunda a través de un puntero global a la aplicación.

bool DelBase::GestorDeEventos(iEvent& ev)
{
       return delbase->GestionaEvento(ev);
}
bool DelBase::GestionaEvento (iEvent& ev)
{
 if (ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess)
 {
   delbase->PreparaCuadro ();
   return true;
 }
 else if (ev.Type == csevBroadcast &&
   ev.Command.Code == cscmdFinalProcess)
 {
   delbase->FinalizaCuadro ();
   return true;
 }
 else if (ev.Type == csevKeyboard && csKeyEventHelper::GetEventType (&ev) == csKeyEventTypeDown && csKeyEventHelper::GetCookedCode (&ev) == CSKEY_ESC)
   {
         csRef<iEventQueue> q (CS_QUERY_REGISTRY (object_reg, iEventQueue));
         if (q)
            q->GetEventOutlet()->Broadcast (cscmdQuit);
         return true;
   }
   return false;
}

[editar] Creación de la geometría del mundo

bool DelBase::CreaMundoDePrueba()
{
 csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY,
       "crystalspace.application.delbase",
       "Aplicación Campo de Juegos del seminario de DelSys 0.1.");
 // Configurar el Gestor de Texturas
 iTextureManager* txtmgr = g3d->GetTextureManager ();
 //txtmgr->SetVerbose (true);
 // Desabilitamos el cache de iluminación ya que el programa es
 // suficientemente sencillo para no necesitarlo.
 engine->SetLightingCacheMode (0);
 // Cargar una textura de la librería estándard
 if (!loader->LoadTexture ("stone", "/lib/std/stone4.gif"))
 {
   csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
       "crystalspace.application.delbase",
       "Error cargando la textura 'stone4'!");
   return false;
 }
 iMaterialWrapper* tm =
   engine->GetMaterialList ()->FindByName ("stone");
 // aquí se guarda la rotación de la cámara
 rotY = rotX = 0;
 // Creamos el Sector
 room = engine->CreateSector ("room");
 // Creamos los muros
 csRef<iMeshWrapper> walls (
   engine->CreateSectorWallsMesh (room, "walls"));
 csRef<iThingState> thing_state (
   SCF_QUERY_INTERFACE (walls->GetMeshObject (), iThingState));
 iThingFactoryState* walls_state = thing_state->GetFactory ();
 walls_state->AddInsideBox (
   csVector3 (-5, 0, -5), csVector3 (5, 20, 5));
 walls_state->SetPolygonMaterial (CS_POLYRANGE_LAST, tm);
 walls_state->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3);
 // Añadimos unas cuantas luces
 csRef<iLight> light;
 iLightList* ll = room->GetLights ();
 light = engine->CreateLight (0, csVector3 (-3, 5, 0), 10,
       csColor (1, 0, 0));
 ll->Add (light);
 light = engine->CreateLight (0, csVector3 (3, 5,  0), 10,
       csColor (0, 0, 1));
 ll->Add (light);
 light = engine->CreateLight (0, csVector3 (0, 5, -3), 10,
       csColor (0, 1, 0));
 ll->Add (light);
 // Preparamos el motor (procesa los objetos que acabamos de crear)
 engine->Prepare ();
 return true;
}

[editar] Inicialización de la cámara

/*-----------------------------*
* Función que inicia la posición de la cámara
* ---------------------------*/
bool DelBase::InicializaCamara()
{
 // Creamos la vista
 view = csPtr<iView> (new csView (engine, g3d));
 // Definir el sector y posición
 view->GetCamera ()->SetSector (room);
 view->GetCamera ()->GetTransform ().SetOrigin (csVector3 (0, 5, -3));
 // Definir el tamaño de la vista
 iGraphics2D* g2d = g3d->GetDriver2D ();
 view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());
}
Herramientas personales