Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   OpenGL (https://www.clubdelphi.com/foros/showthread.php?t=82286)

mirkogonzales 19-02-2013 15:50:47

OpenGL
 
Hola Gente!

Soy nuevo en el foro y en OpenGL. Extoy intentando dibujar una plano pseudo-infinito pero no he podido saber como debo encararlo o conseguir un ejemplo.

Agradezco vuestra ayuda y les envío un saludo.

Mirko.

Casimiro Notevi 19-02-2013 16:24:43

Bienvenido a clubdelphi, ¿ya leiste nuestra guía de estilo?, gracias por tu colaboración :)

Y recuerda poner títulos descriptivos en tus preguntas, gracias ;)

mirkogonzales 22-02-2013 14:29:33

Si ya las he leido y si alguien me podria orientar se los agradeceria. He leido varios tutoriales y libritos (ademas de foros en otros idiomas) pero no le encuentro solución. Gracias y saludos.

mamcx 22-02-2013 15:24:11

A que no le encuentras solucion? No presupongas que es obvio lo que preguntas. Haz de cuenta que cuando se hace una pregunta es a niños de 6 años, que , coincidencialmente, sabemos programar.

Haz intentado escribir algun codigo? Sino, ese es el PRIMER paso. Recuerdo que para cierto proyecto en el que estoy llevaba varios *meses* preocupado como rayos lo haria, y mucho se resolvio cuando abri el IDE, y empece a escribir codigo. Aun cuando este errado, la sola tarea de empezar a trabajar aclara mucho la mente.

fenixariel 20-03-2013 05:37:44

Si es OpenGL tienes que tener en cuenta que es digamoslo asi otro lenguaje, confuso extenso, que tendras que aprender, nada que ver con Object Pascal.

Tienes varios libros y a alguno de ellos tendras que echar mano, el libro rojo de OpenGL, el azul, etc, etc.

Todo lo que puedas escribir en OpenGL, sirve para cualquier lenguaje, con eso te dije todo.


Si te interesa, de echo que lo vas a hacer.


Tambien puedes probar con GLScene, una gran libreria de componentes VCL, que esta a un nivel mayor que OpenGL.


Me gusto una libreria que se llama ZenGL. http://zengl.org/
y al parecer a la gente de Big Fish Games http://www.bigfishgames.es/ les gusta usarla.
http://zengl.org/projects.html


Date una vuelta por: http://www.pascalgamedevelopment.com/content.php


Saludos.

Ñuño Martínez 22-03-2013 10:08:25

Cita:

Empezado por fenixariel (Mensaje 457144)
Me gusto una libreria que se llama ZenGL. http://zengl.org/
(...)
Date una vuelta por: http://www.pascalgamedevelopment.com/content.php

El problema es que ZenGL es una biblioteca para realizar juegos 2D, y lo que mirkogonzales pregunta es un problema tridimensional (o al menos es lo que deduzco).

En Pascal Game Development hay varios expertos, pero quizá también te merezca la pena visitar NeHe, en GameDev.

cesarsoftware 22-03-2013 16:17:00

Cita:

Empezado por mirkogonzales (Mensaje 455411)
Si ya las he leido y si alguien me podria orientar se los agradeceria. He leido varios tutoriales y libritos (ademas de foros en otros idiomas) pero no le encuentro solución. Gracias y saludos.

En fin, mirko, tendre que echante una mano:)

En un nuevo formulario añade el uses "OpenGL" y a partir del codigo que muestro tendras que trabajar un poco, pero la base ya te la doy echa. Basicamente lo que hace es iniciar el contexto opengl, cerrando y diseñar el "cubo" de trabajo, espero que te sirva.

Código Delphi [-]
uses Form, OpenGl, etc.

procedure TfrmOpenGl.glInicia;
var
  PixelFormat : Integer;
  pfd : PIXELFORMATDESCRIPTOR;
begin
  // Leer el dispositivo de contexto en la ventana
  h_DC := GetDC(frmOpenGl.Handle);
  if h_DC = NULL then begin
    Application.MessageBox('No se ha asignado contexto de formulario',
                           'frmOpenGl', MB_OK or MB_ICONERROR);
    Exit;
  end;
  // Poner todos los campos de pixelformatdescriptor a cero
  ZeroMemory(@pfd, SizeOf(pfd));
  // Inicializar solo los campos necesarios
  pfd.nSize       := SizeOf(PIXELFORMATDESCRIPTOR);
  pfd.nVersion    := 1;
  pfd.dwFlags     := PFD_DRAW_TO_WINDOW
                     or PFD_SUPPORT_OPENGL
                     or PFD_DOUBLEBUFFER;
  pfd.iPixelType  := PFD_TYPE_RGBA;
  pfd.cColorBits  := 16;
  pfd.cDepthBits  := 16;
  // Comprobar que se soporta el descriptor de pixeles
  PixelFormat := ChoosePixelFormat(h_DC, @pfd);
  if (PixelFormat = 0) then begin
    glAcaba();
    MessageBox(0, 'No puedo cambiar el descriptor de pixeles', 'Error',
               MB_OK or MB_ICONERROR);
    Exit;
  end;
  // Especificar el descriptor de pixeles
  if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) then begin
    glAcaba();
    MessageBox(0, 'No puedo definir un formato de pixeles', 'Error',
               MB_OK or MB_ICONERROR);
    Exit;
  end;
  // Crear el contexto de generación OpenGl sobre el formulario/ventana
  h_RC := wglCreateContext(h_DC);
  if (h_RC = 0) then begin
    glAcaba();
    MessageBox(0, 'No puedo crear el contexto OpenGL sobre el formulario',
               'Error', MB_OK or MB_ICONERROR);
    Exit;
  end;
  // Activar el contexto de generación OpenGl sobre la ventana
  if (not wglMakeCurrent(h_DC, h_RC)) then begin
    glAcaba();
    MessageBox(0, 'No puedo activar el contexto de generación OpenGl', 'Error',
               MB_OK or MB_ICONERROR);
    Exit;
  end;
  // Seleccionar la ventana de visualización
  SetForegroundWindow(frmOpenGl.Handle);
  // Activar correccion de perpectiva para dibujado rapido
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  glIniciaLuz();
end;

procedure TfrmOpenGl.glAcaba();
begin
  // Quitar la definición de contexto del formulario
  if (not wglMakeCurrent(h_DC, 0)) then begin
    MessageBox(0, 'Devolver recursos OpenGl', 'Error',
               MB_OK or MB_ICONERROR);
    h_DC := null;
  end;
  // Devolver el contexto de generación OpenGL
  if (not wglDeleteContext(h_RC)) then begin
    MessageBox(0, 'Borrar contexto OpenGl', 'Error',
               MB_OK or MB_ICONERROR);
    h_RC := 0;
  end;
end;

procedure TfrmOpenGl.glAjustaVentana();
var
  rojo, verde, azul: glDouble;
  w, h, i, c: Integer;
  newExtX, newExtY, newExtZ: glDouble;
begin
  Val(EditAreaX.Text, i, c);
  if c = 0 then extX := i;  // ancho del area de trabajo
  Val(EditAreaY.Text, i, c);
  if c = 0 then extY := i;  // alto del area de trabajo
  Val(EditAreaZ.Text, i, c);
  if c = 0 then extZ := i;  // fondo del area de trabajo
  w := frmOpenGl.Width; // ancho del formulario
  h := frmOpenGl.Height - 30; // alto del formulario - titulo
  glViewport(0, 0, w, h); // ajusta la vista a la ventana
  // factor alto, ampliación baja
  newExtX := extX; newExtY := extY; newExtZ := extZ;
  if SpinZoom.Position > 99 then SpinZoom.Position := 99;
  newExtX := newExtX - ((SpinZoom.Position * newExtX) / 100);
  newExtY := newExtY - ((SpinZoom.Position * newExtY) / 100);
  newExtZ := newExtZ - ((SpinZoom.Position * newExtZ) / 100);
  glMatrixMode(GL_PROJECTION); // la matriz activa es la de proyección
  glLoadIdentity();            // reinicia el sistema de coordenadas
  // establece el volumen de trabajo izqda, dcha, abajo, arriba, cerca, lejos
  if w <= h then begin
    glOrtho(-newExtX, newExtX,
            -newExtY * h / w, newExtY * h / w,
            -newExtZ * 100, newExtZ * 100);
  end else begin
    glOrtho(-newExtX * w / h, newExtX * w / h,
            -newExtY, newExtY,
            -newExtZ * 100, newExtZ * 100);
  end;
  glMatrixMode(GL_MODELVIEW); // la matriz activa es la del modelador
  glLoadIdentity();           // reinicia el sistema de coordenadas
  // color de fondo y borrado
  rojo := 0; verde := 0; azul := 0;
  Val(SimCfg.SpinRojo.Text, i, c);
  if c = 0 then rojo := i / 100;
  Val(SimCfg.SpinVerde.Text, i, c);
  if c = 0 then verde := i / 100;
  Val(SimCfg.SpinAzul.Text, i, c);
  if c = 0 then azul := i / 100;
  glClearColor(rojo, verde, azul, 1.0);
  glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT);
end;

mirkogonzales 09-04-2013 14:11:37

Muchas gracias por sus respuestas... No es exactamente lo buscado pero me ha sido de mucha utilidad... Me interesaria reiterar la pregunta a nivel conceptual... Imaginen que soy un objeto que se encuentra en el centro de la pantalla y a su alrededor un plano pseudoinfinito que llega hasta el horizonte... como hago para saber en los extremos de la pantalla a que punto de este plano pertenecen? De esta forma podria hacer un bucle que dibuje hasta ahi.... gracias.

cesarsoftware 09-04-2013 14:54:54

Cita:

Empezado por mirkogonzales (Mensaje 458306)
Muchas gracias por sus respuestas... No es exactamente lo buscado pero me ha sido de mucha utilidad... Me interesaria reiterar la pregunta a nivel conceptual... Imaginen que soy un objeto que se encuentra en el centro de la pantalla y a su alrededor un plano pseudoinfinito que llega hasta el horizonte... como hago para saber en los extremos de la pantalla a que punto de este plano pertenecen? De esta forma podria hacer un bucle que dibuje hasta ahi.... gracias.

:eek:
Pero si te lo dado escrito;)
En OpenGL necesitas un cubo que es el area tridimensional de dibujo. Pero tu pantalla es 2D, ose un formulario.
Las funciones Glinicia y Glacaba, son para crear y quitar el contexto OpenGL.
La funcion AjustaVentana crea ese cubo de trabajo en un formulario de las dimensiones que tu quieras.

Y para dibujar el plano que quieres tendrias que usar las siguientes funciones (donde x,y,z es la posicion del plano dentro del cubo tridimensional)
Código Delphi [-]
procedure TfrmOpenGl.DibujaPlanoX(x: Double);
begin
  glNewList(8, GL_COMPILE_AND_EXECUTE);
  // plano X
  glColor3f(0.7, 0.5, 0.0); // naranja
  glPolygonMode(GL_FRONT_AND_BACK, shapeX);
  glBegin(GL_QUADS);
    glVertex3f(x, -extY, -extZ);
    glVertex3f(x, -extY, extZ);
    glVertex3f(x, extY, extZ);
    glVertex3f(x, extY, -extZ);
  glEnd();
  glEndList();
  glCallList(8);
end;

procedure TfrmOpenGl.DibujaPlanoY(y: Double);
begin
  glNewList(9, GL_COMPILE_AND_EXECUTE);
  // plano Y
  glColor3f(0.8, 0.5, 0.0); // naranja
  glPolygonMode(GL_FRONT_AND_BACK, shapeY);
  glBegin(GL_QUADS);
    glVertex3f(-extX, y, -extZ);
    glVertex3f(-extX, y, extZ);
    glVertex3f(extX, y, extZ);
    glVertex3f(extX, y, -extZ);
  glEnd();
  glEndList();
  glCallList(9);
end;

procedure TfrmOpenGl.DibujaPlanoZ(z: Double);
begin
  glNewList(10, GL_COMPILE_AND_EXECUTE);
  // plano Z
  glColor3f(0.9, 0.5, 0.0); // naranja
  glPolygonMode(GL_FRONT_AND_BACK, shapeZ);
  glBegin(GL_QUADS);
    glVertex3f(-extX, extY, z);
    glVertex3f(extX, extY, z);
    glVertex3f(extX, -extY, z);
    glVertex3f(-extX, -extY, z);
  glEnd();
  glEndList();
  glCallList(10);
end;

Mas claro no lo puedo dejar, pero ten en cuenta que como te han dicho antes, tienes que trabajar y aprender sobre la marcha. Con el codigo que he puesto tienes la base para trabajar en opengl con delphi y lo hago porque se lo mucho que me costo a mi comenzar, la proxima consulta que sea con algo de codigo porfa:)

Saludos.

mirkogonzales 11-04-2013 20:41:28

Muchas gracias... Es cierto hay muy poca info sobre esto... Voy a estudiar y luego comento...

blackx5n 16-04-2013 04:28:35

OpenGL
 
cesarsoftware:

Me parecio muy interesante el codigo que posteaste lo trate de probar pero no me funciono use D7


Tengo varias preguntas
1- Que version de delphi usaste para el codigo que posteaste
2- Tengo que tener instalado el opengl que version, o solo funciona con agregar al uses opengl.
3- Que tipo de variables son h_DC y h_RC de el procedimiento glInicia;
4- Que tipo de componente es el SpinZoom y SimCfg
5- Que procedimiento es el glIniciaLuz();

De antemano muchas gracias

cesarsoftware 16-04-2013 18:29:41

Cita:

Empezado por blackx5n (Mensaje 458667)
1- Que version de delphi usaste para el codigo que posteaste

Delphi 2007
Cita:

Empezado por blackx5n (Mensaje 458667)
2- Tengo que tener instalado el opengl que version, o solo funciona con agregar al uses opengl.

solo agrega en el uses la unidad opengl
Cita:

Empezado por blackx5n (Mensaje 458667)
3- Que tipo de variables son h_DC y h_RC de el procedimiento glInicia;

Son handles, necesitas la unidad windows en el uses en mi caso son globales
h_DC : HDC; // handle del contexto del formulario
h_RC : HGLRC; // handle del contexto OpenGL
Cita:

Empezado por blackx5n (Mensaje 458667)
4- Que tipo de componente es el SpinZoom y SimCfg

SpinZoom: TUpDown;
SimCfg es un formulario que contiene la configuracion base
Cita:

Empezado por blackx5n (Mensaje 458667)
5- Que procedimiento es el glIniciaLuz();

Código Delphi [-]
procedure TfrmOpenGl.glIniciaLuz();
begin
  ambientLight[1] := 0.30;
  ambientLight[2] := 0.30;
  ambientLight[3] := 0.30;
  ambientLight[4] := 1.0;
  diffuseLight[1] := 0.1;
  diffuseLight[2] := 0.1;
  diffuseLight[3] := 0.1;
  diffuseLight[4] := 1.0;
  specularLight[1] := 0.5;
  specularLight[2] := 0.5;
  specularLight[3] := 0.5;
  specularLight[4] := 0.5;
  specurefLight[1] := 1.0;
  specurefLight[2] := 1.0;
  specurefLight[3] := 1.0;
  specurefLight[4] := 1.0;
  positionLight[1] := 0.0;
  positionLight[2] := 0.0;
  positionLight[3] := 150.0;
  positionLight[4] := 1.0;
end;

procedure TfrmOpenGl.glAjustaLuz();
begin
  // Definir Luz numero 0
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambientLight);
  glLightfv(GL_LIGHT0, GL_AMBIENT, @ambientLight);       // luz ambiente
  glLightfv(GL_LIGHT0, GL_DIFFUSE, @diffuseLight);       // luz difusa
  glLightfv(GL_LIGHT0, GL_SPECULAR, @specularLight);     // luz especular
  glLightfv(GL_LIGHT0, GL_POSITION, @positionLight);     // posiciona la luz
  if SpinLuzFoco.Value <> 0 then begin
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90);             // Angulo corte a 90º
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, SpinLuzFoco.Value); // Foco brillante
  end else begin
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);              // Angulo corte a 180º
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0);            // sin Foco
  end;
  glEnable(GL_LIGHT0);                                   // enciende luz nº 0
  glEnable(GL_COLOR_MATERIAL); // activa seguimiento del color
  glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);  // material sigue a color
  glMaterialfv(GL_FRONT, GL_SPECULAR, @specurefLight);// reflexivo especular
  glMaterial(GL_FRONT_AND_BACK, GL_SHININESS, 32);       // brillo moderado
end;

procedure TfrmOpenGl.BotonResetLuzClick(Sender: TObject);
begin
  glIniciaLuz();
  SpinLuzAmbiente.Value := 0;
end;

procedure TfrmOpenGl.SpinLuzAmbienteChange(Sender: TObject);
begin
  if EsNumero(SpinLuzAmbiente.Text) then begin
    ambientLight[1] := SpinLuzAmbiente.Value / 100;
    ambientLight[2] := SpinLuzAmbiente.Value / 100;
    ambientLight[3] := SpinLuzAmbiente.Value / 100;
    ambientLight[4] := 1.0;
    glDibuja();
  end;
end;

cesarsoftware 16-04-2013 19:50:19

He grabado un pequeño video de lo que hacen esas funciones que he publicado.:)



Espero que os aclaren algo.

Un saludo.

blackx5n 17-04-2013 03:16:53

OpenGL
 
Muchas gracias cesarsoftware por aclarar estas dudas que tenia, has sido claro y especifico, gracias por el video.

Se llego a tener otra duda aqui mismo posteare.

Salu2 :)

jfh900 19-04-2013 03:36:02

Realmente no sería más interesante utilizar GLScene. Una gran parte de las funciones de OpenGL están encapsuladas en sus componentes, siendo muy facil realizar un primer programa, ya que la programación es mediante componentes visibles.

Un saludo

mirkogonzales 19-04-2013 15:34:13

Es muy interesante lo publicado... Pero igual sigo sin entender cual seria la forma de generar el plano pseudo infinito...

cesarsoftware 19-04-2013 17:47:14

Cita:

Empezado por mirkogonzales (Mensaje 458306)
Me interesaria reiterar la pregunta a nivel conceptual... Imaginen que soy un objeto que se encuentra en el centro de la pantalla y a su alrededor un plano pseudoinfinito que llega hasta el horizonte... como hago para saber en los extremos de la pantalla a que punto de este plano pertenecen? De esta forma podria hacer un bucle que dibuje hasta ahi.... gracias.

Cita:

Empezado por mirkogonzales (Mensaje 458306)
Es muy interesante lo publicado... Pero igual sigo sin entender cual seria la forma de generar el plano pseudo infinito...

Entonces te falta entender "el concepto" y eso es un problema "de base"
El concepto es algo dificil de explicar en un post, pero lo intentare.

A ver, opengl tiene como escenario un cubo tridimensional infinito y este se representa en una pantalla bidimensional finita, y te he enseñado como dibujar un plano que cubra ese infinito en cualquiera de sus tres ejes y te he mostrado como crear un objeto en el centro de ese cubo (ademas de la iluminacion que es MUY importante en las tres dimensiones para, por ejemplo, saber que esta delante de otra cosa, porque produce, entre otras cosas, sombras)
Y por otro lado y no menos importante es que parte del cubo estas viendo, osea lo que en opengl se denomina "camara del observador", no es lo mismo mirar desde arriba, desde abajo o desde un angulo.

Vale, Tu NO tienes que saber que puntos de la pantalla corresponden a ese cubo infinito. Tu YA sabes que puntos son porque TU los has puesto ahi.

Si lo que quieres es un efecto de movimiento tipo navegador, lo que tienes que hacer es crear un cubo de tamaño concreto, digamos un kilometro (luego podras hacer zoom), le haces un plano sobre el eje vertical (que puede ser X,Y o Z, tu mismo), dibujas un cochecito (con glbegin(quads)), colocas la camara del observador sobre la cara sur del cubo (osea tus ojos) y segun se va moviendo el cochecito desplazas el cubo hacia el norte.

Si con esto no entiendes "el concepto", quizas tengas que recurrir a otro porque a mi no se me ocurre como explicarlo mas sencillo.

:)


La franja horaria es GMT +2. Ahora son las 07:20:58.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi