Etiquetas

C (31) Cpp (28) Linux (14) asm (8) Telegram (5) bot (5) libreria (5) Algoritmo (3) Errores comunes (3) python (3) Opengl (2) kali (2) Android (1) Snippet (1) nano (1) recursividad (1)
Mostrando las entradas con la etiqueta libreria. Mostrar todas las entradas
Mostrando las entradas con la etiqueta libreria. Mostrar todas las entradas

miércoles, 22 de mayo de 2024

Colores c.nanorc

## Syntax highlighting for C and C++ files. syntax c "\.([ch](pp|xx)?|C|cc|c\+\+|cu|H|hh|ii?)$" header "-\*-.*\" # Labels. color brightmagenta "^[[:blank:]]*[A-Z_a-z][0-9A-Z_a-z]*:[[:blank:]]*$" color normal ":[[:blank:]]*$" # Types and related keywords. color green "\<(auto|bool|char|const|double|enum|extern|float|inline|int|long|restrict|short|signed|sizeof|static|struct|typedef|union|unsigned|void)\>" color green "\<([[:lower:]][[:lower:]_]*|(u_?)?int(8|16|32|64))_t\>" color green "\<(_(Alignas|Alignof|Atomic|Bool|Complex|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>" color green "\<(class|explicit|friend|mutable|namespace|override|private|protected|public|register|template|this|typename|using|virtual|volatile)\>" # Flow control. color brightyellow "\<(if|else|for|while|do|switch|case|default)\>" color brightyellow "\<(try|throw|catch|operator|new|delete)\>" color magenta "\<(break|continue|goto|return)\>" # Single-quoted stuff (characters, backslash escapes, hex and octal byte codes). color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'" # GCC builtins. color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__" # Strings and names of included files. color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>" # Preprocessor directives. color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$" color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|endif|include(_next)?|line|undef)\>|$)" # Comments. color brightblue "//.*" color brightblue start="/\*" end="\*/" # Reminders. color brightwhite,yellow "\<(FIXME|TODO|XXX)\>" # Trailing whitespace. color ,green "[[:space:]]+$"

domingo, 10 de diciembre de 2023

Primeros pasos en Opengl

/*Este tutorial cubre los primeros conceptos previos a la
creación de aplicaciones con OpenGL y en general a la
creación de contenido 3d. Es necesario aclarar que el
tutorial, por simplicidad y extensión se enfoca sobre la
especificación 1.1 de OpenGL, es decir, solo se menciona la
funcionalidad de la llamada “Fixed Pipeline” (ahora con la
entrada de OpenGL 2.0 y la introducción de los shader al
estándar, la estructura cambio).

En el tutorial se mencionan algunas palabras en ingles,
acompañadas de su traducción al español, solo para conservar
el término original (en ingles) y facilitar la búsqueda
posterior del término, tanto en español, como en inglés.

¿Qué es OpenGL? : OpenGL (Open Graphics Library) es un API
(de Aplication Programming Interface, Interfaz de
Programación de Aplicaciones) libre, multiplataforma,
orientado a la creación de contenido 3d. A un nivel más
simple se puede decir que es una librería que permite hacer
software con gráficos 3d sin preocuparse por el hardware en
que se va a ejecutar y que tiene un gran soporte en diferentes
sistemas operativos como Windows, OS/2, UNIX, FreeBSD , Linux,
etc.
Hay que hacer una diferencia clara, OpenGL no es un lenguaje
de programación, pero se puede trabajar con él desde
diferentes lenguajes como c++, c#, java y Visual Basic.

¿Para que puedo usar OpenGL? : OpenGL puede ser usado para
todo tipo de aplicaciones que necesiten visualización 3d en
tiempo real de alto rendimiento y calidad, en esto están
incluido los videojuegos, CAD, aplicaciones científicas,
médicas, militares, simuladores, etc.

¿Qué necesito para utilizar OpenGL en mis programas? Es buena
idea utilizar un IDE como Visual Studio, Eclipse o DevCpp
para realizar los programas, ya que facilita mucho el trabajo,
adicionalmente, en los archivos fuente donde se utilicen
funciones de OpenGL es necesario incluir las bibliotecas de
prototipos gl.h y glu.h, que generalmente se encuentran
preinstaladas no solo en Visual Studio, sino en otros entornos
donde se soporta el uso de OpenGL. También es necesario hacer
un link con las librerías binarias, en Visual Studio las dos
cosas se verían como:
*/
//Inclusión de las librerías prototipo
#include <gl/gl.h>
#include <gl/glu.h>

//Link con las librerías binarias
#pragma comment(lib, “opengl32.lib”)
#pragma comment(lib, “glu32.lib”)

/*es necesario pasar a algunos conceptos fundamentales del 3d.

SISTEMAS DE COORDENADAS
Para trabajar gráficos bien sea 2d o 3d es necesario tener una
forma de describir la posición de un objeto cualquiera en el
espacio. Para esto es necesario establecer un patrón de
referencia, lo cual se hace generalmente a través de un
sistema de coordenadas y el sistema al que mas estamos
acostumbrados es el de coordenadas cartesianas, en el cual un
punto puede ser expresado como una distancia a través uno (x),
dos (x,y) o tres ejes (x,y,z) mutuamente perpendiculares que
se intersecan en el punto (0,0) en el caso de dos dimensiones
y (0,0,0) en el caso de tres.
OpenGL maneja los sistemas 2d y 3d, aunque el sistema de 2d
sobre píxeles en pantalla es bastante ineficiente, por lo que
en la mayoría de los casos mejor utilizar 3d y simular el 2d
con una proyección ortográfica de la escena.
Si bien la forma en que se representan las coordenadas
cartesianas en matemáticas es bastante estándar (‘x’ positivo
a la derecha y ‘y’ positivo arriba), en los sistemas de dibujo
en el computador hay variaciones dependiendo del sistema de
dibujo sobre el cual se esté trabajando y el caso del 3d es
totalmente dependiente de desde donde, hacia donde y que es
“arriba”. Esto quiere decir que las coordenadas del sistema
abstracto no tienen que ser concordantes con el sistema de
coordenadas sobre la pantalla, por lo que se deber realizar
un proceso llamado mapeo de coordenadas. En este caso el
mapeo debe hacerse del sistema abstracto de coordenadas de
OpenGL al sistema de coordenadas en ventana del sistema
operativo (window, UNIX, linux, mac, etc). El siguiente
esquema muestra tres posibles formas de realizar el mapeo de
coordenadas
El grafico muestra tres de las posibles formas de realizar el
mapeo las coordenadas. En el Modo 1, el punto (0,0) en
coordenadas de dibujo es el correspondiente al extremo
inferior izquierdo de la ventana y el punto (200,200) estará
en el extremo superior derecho. Tal vez es uno de los modos
que parece más “natural”

En el Modo 2, el punto (0,0) en coordenadas de dibujo es el
centro de la ventana y los puntos extremos estarán situados en
los cuatro cuadrantes, en (100,100) superior derecha,
(-100,100) superior izquierda, (-100.-100) inferior izquierda
y (100,-100) inferior derecha. Este modo es similar a la forma
en que lo muestra la cámara por defecto de OpenGL, con el
agregado del eje ‘z’ positivo “saliendo” de la pantalla.

En el Modo 3, el punto (0,0) en coordenadas de dibujo se
encuentra en el extremo superior izquierdo de la ventana y el
punto (200,200) corresponde al extremo inferior derecho. Hay
que notar, que en este modo el eje ‘y’ positivo se encuentra
“cabeza abajo”, es decir, cuando un punto aumenta su
coordenada ‘y’ va hacia abajo, no hacia arriba. Este modo es
usado generalmente por los dispositivos de hardware y es la
forma por defecto de GDI.

Estas son solo algunas formas de mapeo de coordenadas y en
cualquier caso y con un poco de matemáticas (matrices de
transformación) se puede pasar de cualquier modo de mapeo a
otro.

PROYECCION

Los monitores actuales de PC, los televisores, las pantallas
de PDA, de celulares y consolas portátiles son todos
dispositivos bidimensionales, la percepción 3d sobre estos
dispositivos se debe a un conjunto de “trucos” para engañar al
ojo humano y hacerle ver objetos “tridimensionales” sobre un
dispositivo bidimensional, el primero de estos trucos es la proyección. La proyección consiste en generar una imagen bidimensional de una escena tridimensional, algo así como sacarle una foto, o pintar un cuadro de la escena. Tal vez las dos mas conocidas y las que permite trabajar OpenGL directamente son la ortográfica y la perspectiva.

Proyección Ortográfica: En este tipo de proyección se trazan rayos paralelos al plano de proyección (son paralelos porque se considera la fuente de “luz”o centro de proyección en el infinito) y la imagen se forma con aquellos rayos que intersequen al objeto. Esto se ve mas claro en el diagrama

 

Proyección en Perspectiva: La fuente de rayos en este caso no se encuentra en el infinito, sino que es un punto localizado llamado punto de fuga. Los rayos que parten del punto de fuga e intersecan al objeto son entonces los que formaran la imagen sobre el plano de proyección  En la proyección en perspectiva los objetos sufren una deformación por la distancia, a medida que los objetos se alejan del plano de proyección “disminuyen” su tamaño justo de la forma en que ocurre cuando un objetos se aleja de nuestros ojos ( en la figura se muestra como los dos objetos a pesar de ser de diferentes tamaños producen una imagen casi del mismo tamaño sobre el plano de proyección, debido a la diferencia de distancias), es por eso, que esta perspectiva es la mas utilizada para dar una sensación de realismo, como la que se necesitan en los juegos, simulaciones y animaciones.  En el caso de OpenGL, tanto en el modo de perspectiva como en el ortográfico se limita la región del espacio sobre la que se realizan los cálculos, a esta región se le llama volumen de vista o volumen de recorte (clipping volume) y en el caso de la perspectiva también se la llama frustrum por la forma que tiene. Dicha región se especifica, ya que los objetos por fuera de este campo a derecha o izquierda no aparecerán en pantalla y aquellos muy lejanos generarán pocos rasgos, por lo que de calcularse consumirían recursos innecesariamente (la consideración de “lejano” depende del programador).  En el caso de la proyección ortográfica el volumen de vista tiene forma de caja rectangular, por lo que se determina fácilmente mediante 6 medidas: near, far, top, bottom, left, right (cerca, lejos, arriba, abajo, izquierda, derecha) y en el caso de proyección, tiene forma de pirámide truncada de base rectangular, que puede ser determinada por el field of view (campo de visión), el aspect ratio ( el alto del plano mas cercano dividido el ancho), near y far.  Hay que anotar que ambos volúmenes se calculan a partir de la posición del observador, que en el caso de OpenGL es la cámara. También hay que observar que las dimensiones del plano más cercano a la cámara pueden ser mayores o menores a las de la ventana, por lo el mapeo de las condenadas no será con relación uno a uno, adicionalmente OpenGL permite definir el viewport (vista), es decir la región sobre la ventana en la que se va a realizar el dibujado, que puede ser menor al tamaño de la ventana.  Hasta este punto el tutorial ha mostrado algunos conceptos básicos relacionados con la forma en que OpenGL trabaja los gráficos tridimensionales, conceptos que posteriormente se verán reflejados en las primeras aplicaciones que se realicen con OpenGL. Es importante tomar en cuenta que un buen manejo del álgebra lineal, los TDA como las pilas y conocimientos en un lenguaje de programación como c++ permitirán avanzar más rápidamente en el aprendizaje del API OpenGL

OpenGL en Dev++

/*Escrito el 6-agosto-2006*/
/*Este tutorial aborda la creación de una ventana en Windows
con un contexto gráfico OpenGL, pero a diferencia de los
tutoriales basados en GLUT o AUX, esta aplicación se
desarrollará a partir de las librerías de Windows, haciendo
todo “manualmente”. Surge la inquietud de ¿por qué hacer este
tutorial, si podría hacerse más fácilmente con GLUT, AUX o
cualquier otra librería?, la respuesta es porque este
tutorial permite conocer mejor la estructura de un programa de
Windows, que es útil si se necesita algo mas de control (y
problemas) sobre la aplicación.
Además, es divertido “ensuciarse” un poco las manos con el API
de Windows de bajo nivel.

PROGRAMANDO ORIENTADO A EVENTOS
Windows y en general los sistemas operativos GUI utilizan una
arquitectura orientada a eventos para manejar la interacción
usuario – sistema – aplicación de manera organizada y
eficiente. El modelo es bastante simple, cada vez que el
usuario realiza una acción, el sistema determina sobre que
aplicación se realizó y le envía un mensaje describiendo la
acción, el programa lee y procesa el mensaje, si es que este
le interesa (un clic sobre el menú por ejemplo) y realiza los
cambios pertinentes.
Un ejemplo con un clic podría ser como este*/

IMAGEN

/*En este caso la aplicación, por ejemplo un juego de
estrategia, averiguaría la posición en la que en la que se
encontraba el puntero cuando se hizo el clic y movería una
unidad a esta posición. Es importante anotar que este modelo
fue creado para ser eficiente en uso de recursos cuando
varias aplicaciones corren “simultáneamente”, un videojuego
por el contrario es una aplicación destinada a consumir
recursos por su naturaleza de aplicación en “tiempo real”, la
razón de esto es que aunque el usuario se tome una siesta, el
videojuego está realizando cálculos, reproduciendo sonidos,
dibujando la pantalla, la IA esta intentando conquistar el
mundo, etc.

LA APLICACION
Las siguientes estructuras y tipos de datos serán usados en
el desarrollo de la aplicación:

HDC: Handle to Device context. Es el identificador de un
Device Context. Un Device Context es una aplicación a través
de la cual tienen que pasar las operaciones de dibujo, para
que estas puedan ser mostradas en un dispositivo físico, en
este caso particular un monitor.

PFD: Píxel Format Descriptor. Estructura que describe las
propiedades de los píxeles en una superficie de dibujado.

HWND: Handle to Window. Es el identificador de una ventana.

WNDCLASS: Estructura que contiene los datos necesarios para
el registro de una clase ventana, como son su nombre, estilo,
función de paso de mensajes, icono, cursor, entre otros.

HGLRC: Handle to GL Render Context. Es el identificador de un
Render Context, similar al HDC, solo que este no es usado por
GDI sino por OpenGL para realizar el dibujado sobre la pantalla.

Es posible dividir esta aplicación en 4 tareas principales:

Crear la ventana win32.
Preparar la ventana y ligarla a OpenGL.
Inicializar OpenGL.
Hacer el ciclo de mensajes y dibujado.

Las macros y variables del programa son:*/

#define VENTANA_ANCHO 640
#define VENTANA_ALTO  480
HDC     hdc=NULL;
HGLRC  hglrc=NULL;
HWND  hWnd=NULL;
HINSTANCE hInstance

/*CREAR LA VENTANA WIN32
Para crear la ventana es necesario llenar el WNDCLASS,
registrarlo y finalmente crear la ventana. El WNDCLASS */
    WNDCLASS    Cwnd;
    hInstance      = GetModuleHandle(NULL);
    Cwnd.style    = CS_OWNDC;
    Cwnd.lpfnWndProc    = (WNDPROC) WndProc;
    Cwnd.cbClsExtra       = 0;
    Cwnd.cbWndExtra     = 0;
    Cwnd.hInstance        = hInstance;
    Cwnd.hIcon    = NULL;
    Cwnd.hCursor            = LoadCursor(NULL, IDC_ARROW);
    Cwnd.hbrBackground   = NULL;
    Cwnd.lpszMenuName   = NULL;
    Cwnd.lpszClassName   = "OpenGL";
    RegisterClass(&Cwnd);

hWnd=CreateWindow("OpenGL","Hola Mundo",
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,100,
100,VENTANA_ANCHO,VENTANA_ALTO,NULL,NULL,hInstance,NULL);

/*
La función GetModuleHandle() obtiene un identificador para la
aplicación actual. Los datos de la estructura WNDCLASS son
los siguientes:

WNDCLASSS{
UINT style : Estilo de la aplicación, en este caso se quiere
un DC propio (CS_OWNDC)

WNDPROC lpfnWndProc : Manejador de mensajes
int cbClsExtra : Bytes extra para la estructura
int cbWndExtra : Bytes extra para la clase

HINSTANCE hInstance : Instancia de la aplicación que crea la
ventana

HICON hIcon : Icono de la ventana, al ser NULL, windows
provee el icono por defecto.

HCURSOR hCursor : Cursor usado al pasar sobre la ventana,
LoadCursor(NULL,IDI_ARROW) es el icono por defecto

HBRUSH hbrBackground : Color del fondo de la ventana,debido a
que todo el espacio de la ventana va a estar ocupado por la
ventana, este valor se provee como NULL

LPCTSTR lpszMenuName : Nombre del recurso que identifica el
menú de la aplicación, es NULL ya que no se utiliza menú.

LPCTSTR lpszClassName : Nombre de la clase que se usara al
registrarla.}

El manejador de mensajes al que hace referencia es en este
caso uno muy simple:*/

LRESULT CALLBACK WndProc
(HWND   hWnd,UINT uMsg,WPARAM wParam,LPARAM    lParam){
switch (uMsg){
case WM_CLOSE:
{PostQuitMessage(0);return 0;}}
return DefWindowProc(hWnd,uMsg,wParam,lParam);}

/*Las entradas de esta función son:

HWND hWnd : Identificador de la ventana que recibe el mensaje
UINT uMsg : El mensaje
WPARAM wParam : Información adicional sobre el mensaje
LPARAM lParam : Información adicional sobre el mensaje

Esta función solo intercepta un mensaje, aquel que es
enviado por el sistema para indicar a la aplicación que debe
cerrarse (WM_CLOSE) y si es cualquier otro mensaje lo envía
al DefWindowProc().
RegisterClass() registra una clase ventana, con los
parámetros dados por un WNDCLASS, en este caso CWnd.
Es hora de crear una ventana a partir de la clase creada con
el RegisterClass(), para esto se utiliza la función
CreateWindow() cuyos parámetros son los siguientes:

HWND CreateWindow(
LPCTSTR lpClassName : Nombre de la clase a partir de la cual
se crea la ventana
LPCTSTR lpWindowName : Titulo de la ventana.
DWORD dwStyle : Estilo de la ventana, en este caso con
titulo y borde (WS_OVERLAPED)
int x, : Posición x de la ventana
int y : Posición y de la ventana
int nWidth : Ancho de la ventana
int nHeight : Alto de la ventana
HWND hWndParent : Identificador de la ventana “padre”, en
este caso NULL, ya que no tiene HMENU menú : Identificador
del menú de la ventana, en este caso NULL, ya que no tiene
HINSTANCE hInstance : Identificador de la aplicación
poseedora de la ventana, en NT/2000/XP este valor es ignorado
LPVOID lpParam : Cadena con el parámetro a pasar al llamar
el mensaje WM_CREATE. En este NULL, ya que no hay ningun
parámetro a pasar)

 PREPARAR LA VENTANA Y LIGARLA A OPENGL.
Ahora es necesario:*/
GLuint  PixelFormat;
static  PIXELFORMATDESCRIPTOR pfd=
{sizeof(PIXELFORMATDESCRIPTOR),1,
PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0};

    hdc=GetDC(hWnd);
    PixelFormat=ChoosePixelFormat(hdc,&pfd);
    SetPixelFormat(hdc,PixelFormat,&pfd);
    hglrc=wglCreateContext(hdc);
    wglMakeCurrent(hdc,hglrc);
/*
El PIXELFORMATDESCRIPTOR tiene los siguientes datos:

PIXELFORMATDESCRIPTOR {
WORD nSize : Tamaño de la estructura
WORD nVersion : Versión de la estructura, siempre es 1

DWORD dwFlags : Propiedades del buffer de píxeles, en este
caso dibujar sobre una ventana (PFD_DRAW_TO_WINDOW), soporte
a OpenGL (PFD_SUPPORT_OPENGL) y doble buffer (PFD_DOUBLEBUFFER)

BYTE iPixelType : La forma de describir los píxeles, en este
caso como RGBA (PFD_TYPE_RGBA)

BYTE cColorBits : Tamaño de un píxel individual en bits, en
este caso 32 que es el mas común
BYTE cRedBits : Ignorado
BYTE cRedShift : Ignorado
BYTE cGreenBits : Ignorado
BYTE cGreenShift : Ignorado
BYTE cBlueBits : Ignorado
BYTE cBlueShift : Ignorado
BYTE cAlphaBits : Ignorado
BYTE cAlphaShift : Ignorado
BYTE cAccumBits : Ignorado
BYTE cAccumRedBits : Ignorado
BYTE cAccumGreenBits : Ignorado
BYTE cAccumBlueBits : Ignorado
BYTE cAccumAlphaBits : Ignorado

BYTE cDepthBits : Bits para el buffer de profundidad, pueden
ser 16 o 32 como en este caso.

BYTE cStencilBits : Ignorado
BYTE cAuxBuffers : Ignorado
BYTE iLayerType : Ignorado
BYTE bReserved : Ignorado
DWORD dwLayerMask : Ignorado
DWORD dwVisibleMask : Ignorado
DWORD dwDamageMask : Ignorado
}

GetDC() obtiene el Device Context asociado a la ventana
identificada por hWnd.

ChoosePixelFormat() utiliza dos parámetros, el hdc sobre el
cual se buscara un formato de píxeles compatible y el pfd que
especifica el formato deseado por la aplicación. Esta función
devuelve el formato de píxeles mas cercano encontrado, con
respecto al pfd.

SetPixelFormat() utilizar tres parámetros, el hdc sobre el
cual se va a establecer el formato de píxeles, un entero, el
PixelFormat, donde esta guardado el índice a dicho formato de
píxeles y el pfd de referencia que se uso para encontrar el
formato, el ultimo valor no afecta el funcionamiento de esta
función, ya que se utiliza solamente como registro.

wglCreateContext() crea un contexto de dibujo para OpenGL, a
partir de un contexto de dibujo de GDI.

wglMakeCurrent() elige un HGLRC sobre el cual se va a dibujar
los OpenGL, esto es debido a que una aplicación puede tener
varios contextos de dibujo, pero solo puede operar un proceso
sobre un contexto a la vez.

INICIALIZAR OPENGL
La inicialización de OpenGL es en este caso bastante simple y
más bien utilitaria, es realizada por las siguientes líneas de
código:*/

glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glMatrixMode (GL_PROJECTION);
glViewport (0, 0, VENTANA_ANCHO , VENTANA_ALTO);
gluPerspective(45.0f,VENTANA_ANCHO/VENTANA_ALTO,0.1f,100.0f);
gluLookAt( 0,0,16,  0,0,0, 0,1,0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

/*
glClearColor() establece el color de fondo
glMatrixMode() escoge una matriz para operar sobre ella.
Primero se elige la de proyección (GL_PROJECTION)

glViewport() establece el tamaño del marco de dibujo de OpenGL

gluPerspective() establece el frustrum, en este caso apertura
de 45, aspecto de 640/480, plano mas visible a 0.1 de
distancia y mas lejano a 100.

gluLookAt() posiciona la "cámara" (en realidad hace
transformaciones sobre la matriz proyección. Los parámetros
están agrupado de a 3 (x, y, z) y representan la posición de
la camara, el punto al que mira y que vector es considerado
"hacia arriba"

Finalmente se vuelve al modo de matriz GL_MODELVIEW que es
el utilizado para dibujar las primitivas.

HACER EL CICLO DE MENSAJES Y DIBUJADO
El ciclo de mensajes se encarga de revisar constantemente los
mensajes, en busca de alguno de interés para la aplicación,
de no haber mensajes, se dibuja la escena de OpenGL. El
código es así
*/

MSG mensaje;
BOOL continuar=TRUE;
while(continuar){

if (PeekMessage(&mensaje,NULL,0,0,PM_REMOVE)){
if (mensaje.message==WM_QUIT){continuar=FALSE;}
else{
TranslateMessage(&mensaje);
DispatchMessage(&mensaje);
}}
else{
render();
SwapBuffers(hdc);
}}

/*
La variable continuar indica cuando el ciclo debe detenerse,
cuando el usuario o el sistema decidan cerrar la aplicación,
bien sea con la X sobre la barra de la ventana, con el método
abreviado, mediante el administrador de aplicaciones, etc.
En algunos ejemplos se obvia esta variable al hacer un ciclo
while(1) y utilizando un break; en caso de recibir el mensaje.

PeekMessage() busca y almacena un mensaje de la pila de
mensajes de la aplicación. Si tal mensaje existe lo almacena
en el primer parámetro y devuelve TRUE, de lo contrario
devuelve FALSE. El ultimo parámetro (PM_REMOVE) le indica a la
función al leer un mensaje debe borrarlo de la pila de mensajes.

En este caso solo estamos observando el mensaje WM_QUIT, que
indica que el WndProc llamo la función PostQuitMessage(), es
decir que intercepto algún mensaje de salida de la aplicación.

Si no es este mensaje, se vuelve a colocar en la pila de
mensajes mediante las funciones TranslateMessage() y
DispatchMessage, para que este pueda ser leído por el
wndProc() creado anteriormente o por el manejador de mensajes
por defecto (DefWindowProc()).

Finalmente si no hay ningún mensaje por leer en la pila de
mensajes, se hace el dibujado(render()) y se cambia de buffer
(SwapBuffers()). El código del render() es bastante simple y
pinta un triangulo
*/

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(3.0f,-2.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glVertex3f(-3.0f,-2.0f,0.0f);
glEnd();

/*
glClear() limpia los buffers pasados como parámetro de acuerdo
al color de limpiado (negro) y entre las funciones glBegin() y
glEnd() esta la especificación de un triangulo de color azul

El codigo entero*/
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#define VENTANA_ANCHO 640
#define VENTANA_ALTO  480

HDC   hdc=NULL;
HGLRC      hglrc=NULL;
HWND        hWnd=NULL;
HINSTANCE   hInstance;

void inicializarGL(void){
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glMatrixMode (GL_PROJECTION);
glViewport (0, 0, VENTANA_ANCHO , VENTANA_ALTO);
gluPerspective(45.0f,VENTANA_ANCHO/VENTANA_ALTO,0.1f,100.0f);
gluLookAt( 0,0,16,  0,0,0, 0,1,0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
    }

void render(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(3.0f,-2.0f,0.0f);
glVertex3f(0.0f,1.0f,0.0f);
glVertex3f(-3.0f,-2.0f,0.0f);
glEnd();
    }

void deInicializar(void){
wglMakeCurrent(NULL,NULL);
wglDeleteContext(hglrc);
ReleaseDC(hWnd,hdc);
DestroyWindow(hWnd);
UnregisterClass("OpenGL",hInstance);
    }

LRESULT CALLBACK WndProc
(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
switch (uMsg){
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}}
return DefWindowProc(hWnd,uMsg,wParam,lParam);}

int WINAPI WinMain
(HINSTANCE hinst,HINSTANCE hinstAnterior,
LPSTR cadenaDeComandos,int parametroVentana){
        MSG  mensaje;
        BOOL    continuar=TRUE;
        GLuint  PixelFormat;
        WNDCLASS    Cwnd;

        hInstance         = GetModuleHandle(NULL);
   Cwnd.style      = CS_OWNDC;
   Cwnd.lpfnWndProc    = (WNDPROC) WndProc;
   Cwnd.cbClsExtra  = 0;
   Cwnd.cbWndExtra  = 0;
   Cwnd.hInstance    = hInstance;
   Cwnd.hIcon      = NULL;
   Cwnd.hCursor        = LoadCursor(NULL, IDC_ARROW);
   Cwnd.hbrBackground  = NULL;
   Cwnd.lpszMenuName   = NULL;
   Cwnd.lpszClassName  = "OpenGL";
   RegisterClass(&Cwnd);

hWnd=CreateWindow("OpenGL","Hola Mundo",WS_OVERLAPPEDWINDOW
,100,100,VENTANA_ANCHO,VENTANA_ALTO,NULL,NULL,hInstance,NULL);

static  PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),1,
PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0};

hdc=GetDC(hWnd);
PixelFormat=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,PixelFormat,&pfd);
hglrc=wglCreateContext(hdc);
wglMakeCurrent(hdc,hglrc);
ShowWindow(hWnd,SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
inicializarGL();

while(continuar){

if (PeekMessage(&mensaje,NULL,0,0,PM_REMOVE)){
if (mensaje.message==WM_QUIT){continuar=FALSE;}
else{
TranslateMessage(&mensaje);
DispatchMessage(&mensaje);
}}

else{
render();
SwapBuffers(hdc);
}}

deInicializar();
return (mensaje.wParam);}

/*Por ultimo:
La aplicación luce así:

Captura

Aun este programa tiene que abarcar bastantes prestaciones no
contempladas, por dar simpleza (de ser posible eso) al
Hola Mundo. Entre estas prestaciones están:

Solicitar modo pantalla completa, que es muy común entre los
videojuegos.

Atender a los errores en todo el proceso de creación de la
ventana y asociación a OpenGL. Muchas de las funciones
utilizadas en la aplicación tienen un retorno que indica si
la función pudo llevarse a cabo o no.

Cambiar de tamaño la escena de OpenGL al cambiar el tamaño de
la ventana. Esto se hace añadiendo los estilos CS_VREDRAW y
CS_HREDRAW al WNDCLASS e interceptando el mensaje
WM_SYSCOMMAND, Wparam SC_SIZE.

Pausar la aplicación cuando la ventana es puesta detrás de
otra o minimizada.

También es importante aclarar que este ejemplo utiliza el
driver de software de OpenGL creado por Microsoft en la
década del 90 y que actualmente dicho driver no es mantenido y
es muy ineficiente. Para utilizar el driver de OpenGL que
proporciona la tarjeta gráfica, que tiene la ventaja de ser
acelerado por hardware y mantenido constantemente
(dependiendo de la tarjeta) se pueden usar las funciones
WGL-ARB aprobadas en el año 2000 y que hacen actualmente
parte del estándar, aunque siempre que se quieran usar, se
debe comprobar su disponibilidad, ya que dependen de la
implementación del estándar.

Finalmente es necesario señalar que esta es una de las maneras
mas complicadas de hacer una aplicación con OpenGL para
Windows, ya que se trabaja el API de win32 a muy bajo nivel y
las funciones para ligar OpenGL con GDI no han sido
actualizada en muchos años, de hecho el articulo relevante mas
reciente que se puede encontrar en MSDN acerca de OpenGL data
del año 1995.*/

viernes, 24 de noviembre de 2023

bot telegram (5) telegram.h

 /*
 * Luis Alberto
 * Twitter @albertobsd
 */


#ifndef __TBOT_H_
#define __TBOT_H_
#include"jsmn.h"

enum chat_type{
chat_private = 0,
chat_group = 1,
chat_supergroup = 2,
chat_channel = 3};

typedef struct{
char *phone_number;
char *first_name;
char *last_name;
int user_id;
}Contact;

typedef struct{
char *file_id;
int duration;
char *mime_type;
int file_size;
}Voice;

typedef struct{
char *file_id;
int width;
int height;
int file_size;
} PhotoSize;

typedef struct{
int length;
PhotoSize **item;
}Photos;

typedef struct{
char *file_id;
PhotoSize *thumb;
char *file_name;
char *mime_type;
int file_size;
}Document;

typedef struct{
char *file_id;
int width;
int height;
PhotoSize *thumb;
int file_size;
}Sticker;

typedef struct{
int id;
enum chat_type type;
char *title;
char *username;
char *first_name;
char *last_name;
}Chat;

typedef struct{
int id;
char *first_name;
char *last_name;
char *username;
}User;

typedef struct{
float longitude;
float latitude;
}Location;

typedef struct{
char *file_id;
int width;
int height;
int duration;
PhotoSize *thumb;
char *mime_type;
int file_size;
}Video;

typedef struct Message {
        int message_id;
        User *from;
        int date;
        Chat *chat;
        User *forward_from;
        int forward_date;
        struct Message *reply_to_message;
        char *text;
        void *audio;
        Document *document;
        Photos *photo;
        Sticker *sticker;
        Video *video;
        Voice *voice;
        char *caption;
        Contact *contact;
        Location *location;
        User *new_chat_participant;
        User *left_chat_participant;
        char *new_chat_title;
        Photos *new_chat_photo;
        int delete_chat_photo;
        int group_chat_created;
        int supergroup_chat_created;
        int channel_chat_created;
        int migrate_to_chat_id;
        int migrate_from_chat_id;
}Message;

typedef struct  {
        char *ok;
        char *result;
        int error_code;
        char *description;
}Response;

typedef struct {
        int update_id;
        int type;
        union  {
                Message *message;
        }item;
}Update;

typedef struct  {
        int length;
        Update **list;
}Updates;

typedef struct  {
        char *file_id;
        int file_size;
        char *file_path;
}File;

typedef struct {
        char *file_id;
        int duration;
        char *performer;
        char *title;
        char *mime_type;
        int file_size;
}Audio;

typedef enum {
        TELEGRAM_ERROR_CURL_= 1,
        TELEGRAM_ERROR_API_RESPONSE = -10,
        TELEGRAM_ERROR_DEVELOPER = -20,
        TELEGRAM_ERROR_UNEXPECTED_TOKEN_TYPE  = -30,
        TELEGRAM_ERROR_UNEXPECTED_TOKEN_VALUE = -40,
        TELEGRAM_ERROR_API_404 = 404
}telegram_error_t;




/*
 * free telegram variables funtions
 */

Response* telegram_free_response(Response *res);
User* telegram_free_user(User *user);
Update* telegram_free_update(Update *update);
Updates* telegram_free_updates(Updates *updates);
Message* telegram_free_message(Message *message);
Document* telegram_free_document(Document *document);
Video* telegram_free_video(Video *video);
Voice* telegram_free_voice(Voice *voice);
Audio* telegram_free_audio(Audio *audio);
Sticker* telegram_free_sticker(Sticker *sticker);
Chat* telegram_free_chat(Chat *chat);
Photos* telegram_free_photos(Photos *photos);
Contact* telegram_free_contact(Contact *contact);
Location* telegram_free_location(Location *location);
PhotoSize* telegram_free_photosize(PhotoSize *photosize);



int telegram_init(char *);
int indexOf(char *str,char **ptr_strings);
int telegram_jsmn_init(jsmn_parser *parser,jsmntok_t **t,char *buffer,int *n);
int telegram_set_error(char *error_str,int error_code);
char * telegram_jsmn_get_token(jsmntok_t token,char *full);
void telegram_dump_token(jsmntok_t token,char *str);
char *telegram_makeurl(char *telegram_method);
char *telegram_get_error();
int telegram_is_error();
char* telegram_build_post(char **variables,char **values);


int telegram_reset_buffer();
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata );
off_t fsize(const char *filename);

/*
 * Telegram API methods
 */

User * telegram_getMe();
Updates * telegram_getUpdates();
Message* telegram_sendMessage(char *postdata);
File* telegram_getFile(char *file_id);
Message* telegram_sendDocument(char *filename,char **variables, char **valores);


/*
 * Telegram parse
 */

User * telegram_parse_user(char *str,int *count);
Response* telegram_parse_response(char *str,int *count);
Updates* telegram_parse_updates(char *str,int *count);
Update* telegram_parse_update(char *str,int *count);
Message* telegram_parse_message(char *str,int *count);
Chat* telegram_parse_chat(char *str,int *count);
PhotoSize* telegram_parse_photosize(char *str,int *count);
Photos* telegram_parse_photos(char *str,int *count);
Sticker* telegram_parse_sticker(char *str,int *count);
Voice* telegram_parse_voice(char *str,int *count);
Location* telegram_parse_location(char *str,int *count);
Contact* telegram_parse_contact(char *str,int *count);
Document* telegram_parse_document(char *str,int *count);
Video* telegram_parse_video(char *str,int *count);
File* telegram_parse_file(char *str,int *count);
char* telegram_downloadFile(File *file,char *name);
char* telegram_process_slash(char *str);
CURL* telegram_curl_init();


#endif /* __TBOT_H_ */

bot telegram (4) jsmn.h

 #ifndef __JSMN_H_
#define __JSMN_H_

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * JSON type identifier. Basic types are:
 *      o Object
 *      o Array
 *      o String
 *      o Other primitive: number, boolean (true/false) or null
 */
typedef enum {
        JSMN_UNDEFINED = 0,
        JSMN_OBJECT = 1,
        JSMN_ARRAY = 2,
        JSMN_STRING = 3,
        JSMN_PRIMITIVE = 4
} jsmntype_t;

enum jsmnerr {
        /* Not enough tokens were provided */
        JSMN_ERROR_NOMEM = -1,
        /* Invalid character inside JSON string */
        JSMN_ERROR_INVAL = -2,
        /* The string is not a full JSON packet, more bytes expected */
        JSMN_ERROR_PART = -3
};

/**
 * JSON token description.
 * @param               type    type (object, array, string etc.)
 * @param               start   start position in JSON data string
 * @param               end             end position in JSON data string
 */
typedef struct {
        jsmntype_t type;
        int start;
        int end;
        int size;
#ifdef JSMN_PARENT_LINKS
        int parent;
#endif
} jsmntok_t;

/**
 * JSON parser. Contains an array of token blocks available. Also stores
 * the string being parsed now and current position in that string
 */
typedef struct {
        unsigned int pos; /* offset in the JSON string */
        unsigned int toknext; /* next token to allocate */
        int toksuper; /* superior token node, e.g parent object or array */
} jsmn_parser;

/**
 * Create JSON parser over an array of tokens
 */
void jsmn_init(jsmn_parser *parser);

/**
 * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
 * a single JSON object.
 */
int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
                jsmntok_t *tokens, unsigned int num_tokens);

#ifdef __cplusplus
}
#endif

#endif /* __JSMN_H_ */