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

Cargando un archivo (.asc)

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

face.jpg

Modelo de un archivo (.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 

Código Fuente

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

//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