Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links

Podemos utilizar el 3D Studio MAX para modelar y texturar un objeto 3D, para que una
ves exportado, lo podamos leer desde nuestro programa en OpenGL.
La idea es exportarlo desde el MAX como un archivo .asc, este es un archivo de texto, podes
utilizar el Block de Notas de Windows, o cualquiere editor de texto para ver su contendido
alli, tenes los vertices, caras y coordenadas de textura del modelo.
Ventajas: Facil de leer.
Desventajas:
Ejemplo de una archivo (.ASC), cubo.zip
Named Object: "Box01" Tri-mesh, Vertices: 8 Faces: 12 Vertex list: Vertex 0: X: 5.051399 Y: 5.003852 Z: -4.986376 Vertex 1: X: 15.051399 Y: 5.003852 Z: -4.986376 Vertex 2: X: 5.051399 Y: 15.003852 Z: -4.986376 Vertex 3: X: 15.051399 Y: 15.003852 Z: -4.986376 Vertex 4: X: 5.051399 Y: 5.003852 Z: 5.013624 Vertex 5: X: 15.051399 Y: 5.003852 Z: 5.013624 Vertex 6: X: 5.051399 Y: 15.003852 Z: 5.013624 Vertex 7: X: 15.051399 Y: 15.003852 Z: 5.013624 Face list: Face 0: A:0 B:2 C:3 AB:1 BC:1 CA:0 Smoothing: 2 Face 1: A:3 B:1 C:0 AB:1 BC:1 CA:0 Smoothing: 2 Face 2: A:4 B:5 C:7 AB:1 BC:1 CA:0 Smoothing: 3 Face 3: A:7 B:6 C:4 AB:1 BC:1 CA:0 Smoothing: 3 Face 4: A:0 B:1 C:5 AB:1 BC:1 CA:0 Smoothing: 6 Face 5: A:5 B:4 C:0 AB:1 BC:1 CA:0 Smoothing: 6 Face 6: A:1 B:3 C:7 AB:1 BC:1 CA:0 Smoothing: 5 Face 7: A:7 B:5 C:1 AB:1 BC:1 CA:0 Smoothing: 5 Face 8: A:3 B:2 C:6 AB:1 BC:1 CA:0 Smoothing: 6 Face 9: A:6 B:7 C:3 AB:1 BC:1 CA:0 Smoothing: 6 Face 10: A:2 B:0 C:4 AB:1 BC:1 CA:0 Smoothing: 7 Face 11: A:4 B:6 C:2 AB:1 BC:1 CA:0 Smoothing: 7 |
El codigo fuente se encuentra dividido en varios archivos main.cpp, asc.cpp, y asc.h
Desacarga del Codigo Fuente, proyecto en VisualC++.
Descarga de los archivo de prueba (.ASC), todos fueron creados con 3DStudio MAX 2.0
knot.asc
jet.asc
face.asc
Desacarga del Ejecutable
//main.cpp
//email = valcoey@hotmail.com
//www = www.geocities.com/valcoey/index.html
#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "asc.h"
#define PI 3.1419592654
Object3D obj;
Point3f *vnormales=0;
float LightPos[] = { 0.0f, 0.0f, 1.0f, 0.0f};
float LightAmb[] = { 0.15f, 0.15f, 0.15f, 1.0f};
float LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f};
float LightSpc[] = { 1.0f, 1.0f, 1.0f, 1.0f};
HDC g_HDC;
bool fullScreen = false;
bool keyPressed[256];
int mouseX, mouseY;
float cameraX, cameraY, cameraZ;
float lookX, lookY, lookZ;
float alfa=0.0f, rho=0.0f;
float Modulo(float x, float y, float z)
{
float len;
len = x*x + y*y + z*z;
return ((float) sqrt(len));
}
void Normalizar(float *x, float *y, float *z)
{
float len;
len = Modulo(*x, *y, *z);
len = (float) 1.0/len;
(*x) *= len;
(*y) *= len;
(*z) *= len;
}
void VectorNormal(Object3D& object, int i)
{
Face& face = object.pFaces[i];
const Point3f& v1 = object.pVertices[face.vertexIndices[0]];
const Point3f& v2 = object.pVertices[face.vertexIndices[1]];
const Point3f& v3 = object.pVertices[face.vertexIndices[2]];
float tempx, tempy, tempz;
tempx=(v2.y-v1.y)*(v3.z-v1.z) - (v2.z-v1.z)*(v3.y-v1.y);
tempy=(v2.z-v1.z)*(v3.x-v1.x) - (v2.x-v1.x)*(v3.z-v1.z);
tempz=(v2.x-v1.x)*(v3.y-v1.y) - (v2.y-v1.y)*(v3.x-v1.x);
Normalizar(&tempx, &tempy, &tempz);
face.normals.x=tempx;
face.normals.y=tempy;
face.normals.z=tempz;
}
void CalcularNormales(void)
{
Point3f sum;
int shared = 0;
int i,j;
vnormales = new Point3f[obj.nVertices];
for (i=0;i<obj.nFaces;i++)
VectorNormal(obj,i);
for (i=0; i<obj.nVertices; i++)
{
for (j=0; j<obj.nFaces; j++)
{
const Face& face = obj.pFaces[j];
if (face.vertexIndices[0]==i ||
face.vertexIndices[1]==i ||
face.vertexIndices[2]==i)
{
sum.x += face.normals.x;
sum.y += face.normals.y;
sum.z += face.normals.z;
shared++;
}
}
vnormales[i].x = (sum.x / (float) shared);
vnormales[i].y = (sum.y / (float) shared);
vnormales[i].z = (sum.z / (float) shared);
Normalizar(&vnormales[i].x, &vnormales[i].y, &vnormales[i].z);
sum.x=0.0;
sum.y=0.0;
sum.z=0.0;
shared = 0;
}
}
void killObject(Object3D& object)
{
delete[] object.pFaces;
object.pFaces = NULL;
object.nFaces = 0;
delete[] object.pVertices;
object.pVertices = NULL;
object.nVertices = 0;
delete [] vnormales;
vnormales = 0;
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
if (!height)
return;
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)width/(GLfloat)height, 1.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Initialize(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);
glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpc);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
LoadScene("face.asc", obj);
CalcularNormales();
}
void Render(void)
{
GLfloat mat_ambient[] = { 0.0f, 0.4648f, 0.7929f, 1.0f };
GLfloat mat_diffuse[] = { 0.1f, 0.5742f, 0.6172f, 1.0f };
GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat mat_shininess[] = { 100.0f };
double rad_alfa=0.0, rad_rho=0.0;
int count, i;
rad_alfa = PI*alfa/180.0;
rad_rho = PI*rho/180.0;
cameraX = (float) (50*sin(rad_rho)*cos(rad_alfa));
cameraZ = (float) (50*sin(rad_rho)*sin(rad_alfa));
cameraY = (float) (50*cos(rad_rho));
lookX = 0.0f;
lookY = 0.0f;
lookZ = 0.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(cameraX, cameraY, cameraZ, lookX, lookY, lookZ, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glBegin(GL_TRIANGLES);
for (count=0; count<obj.nFaces; count++)
{
const Face& face = obj.pFaces[count];
for (i=0; i<3; i++)
{
const Point3f& vertex = obj.pVertices[face.vertexIndices[i]];
glNormal3f(vnormales[face.vertexIndices[i]].x,
vnormales[face.vertexIndices[i]].y,
vnormales[face.vertexIndices[i]].z);
glVertex3f(vertex.x, vertex.y, vertex.z);
}
}
glEnd();
glFlush();
SwapBuffers(g_HDC);
}
void SetupPixelFormat(HDC hDC)
{
int nPixelFormat;
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,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0 };
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HGLRC hRC;
static HDC hDC;
int width, height;
int oldMouseX, oldMouseY;
switch(message)
{
case WM_CREATE:
hDC = GetDC(hwnd);
g_HDC = hDC;
SetupPixelFormat(hDC);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return 0;
break;
case WM_CLOSE:
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
PostQuitMessage(0);
return 0;
break;
case WM_SIZE:
height = HIWORD(lParam);
width = LOWORD(lParam);
if (height==0)
{
height=1;
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,1.0f,500.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 0;
break;
case WM_KEYDOWN:
keyPressed[wParam] = true;
return 0;
break;
case WM_KEYUP:
keyPressed[wParam] = false;
return 0;
break;
case WM_MOUSEMOVE:
oldMouseX = mouseX;
oldMouseY = mouseY;
mouseX = LOWORD(lParam);
mouseY = HIWORD(lParam);
if ((mouseY - oldMouseY)>0)
rho +=5.1f;
else if ((mouseY - oldMouseY)<0)
rho -=5.1f;
if ((mouseX - oldMouseX)>0)
alfa += 5.1f;
else if ((mouseX - oldMouseX)<0)
alfa -= 5.1f;
return 0;
break;
default:
break;
}
return (DefWindowProc(hwnd, message, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX windowClass;
HWND hwnd;
MSG msg;
bool done;
DWORD dwExStyle;
DWORD dwStyle;
RECT windowRect;
int width = 550;
int height = 400;
int bits = 32;
windowRect.left=(long)0;
windowRect.right=(long)width;
windowRect.top=(long)0;
windowRect.bottom=(long)height;
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = "MyClass";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if (!RegisterClassEx(&windowClass))
return 0;
if (fullScreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width;
dmScreenSettings.dmPelsHeight = height;
dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
fullScreen=FALSE;
}
}
if (fullScreen)
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
hwnd = CreateWindowEx(NULL,
"MyClass",
"Demo OpenGL (.asc)",
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0,
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top,
NULL,
NULL,
hInstance,
NULL);
if (!hwnd)
return 0;
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
done = false;
Initialize();
while (!done)
{
PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT)
{
done = true;
}
else
{
if (keyPressed[VK_ESCAPE])
done = true;
else
{
Render();
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
killObject(obj);
if (fullScreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(TRUE);
}
return msg.wParam;
}
|

valcoey@hotmail.com
Ramiro Alcocer, 2001
Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links