Principal | Gráficos 3D | Gráficos 2D | Fractales | Math | Códigos | Tutoriales | Links
El siguiente código carga un archivo .ASC, es un archivo de texto que contiene
vertices, caras, luces, camaras, materiales, de un modelo 3D, creado por programas de animacion y modelado 3D, ejemplo 3DStudioMAX, 3D Studio R4, mi código solo carga los vertices y las caras de una escena formada por un solo objeto, ignorando las luces, camaras, y materiales, el propio programa crea la fuente de luz y una camara. El calculo de las normales de iluminacion es realizada por el programa, utilizando la informacion de los vertices y caras que forman el objeto.
cualquier comentario o sugerencia a valcoey@hotmail.com, en estos momentos estoy
viendo como poder cargar multiples objetos, incluyendo sus materiales y texturas
si alguien tiene algunas ideas? :-).
La siguiente imagen es la representacion del archivo face.asc
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.oocities.org/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