|
DIBUJO ASISTIDO POR ORDENADOR LISTADO 7 |
Este programa ha sido creado con el compilador
Borland C/C++ 3.1,
utilizando el modelo LARGE de memoria.
Su funcionamiento se puede comprobar con
alguno de estos objetos 3D.
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <alloc.h>
#include <math.h>
typedef struct {
int nv, *v;
float z;
} ELEM;
float matt[4][4], matr[4][4], matp[4][4];
void mmat (float a[4][4], float b[4][4])
{
int i, j, k;
float c[4][4];
for (i=0;i<4;i++)
for (j=0;j<4;j++) {
c[i][j]=0.;
for (k=0;k<4;k++)
c[i][j] +=a[i][k]*b[k][j];
}
for (i=0;i<4;i++)
for (j=0;j<4;j++)
b[i][j]=c[i][j];
}
void proyecta (float p[4], float q[4])
{
int i, j;
for (i=0;i<4;i++) {
q[i]=0.;
for (j=0;j<4;j++)
q[i] +=p[j] * matp[j][i];
}
for (i=0;i<3;i++)
q[i] /= q[3];
}
void rota (char eje, float a)
{
float ang=a * M_PI / 180.;
if (eje=='X') {
matr[0][0]=1; matr[0][1]=0; matr[0][2]=0; matr[0][3]=0;
matr[1][0]=0; matr[1][1]=cos(ang); matr[1][2]=sin(ang); matr[1][3]=0;
matr[2][0]=0; matr[2][1]=-sin(ang); matr[2][2]=cos(ang); matr[2][3]=0;
matr[3][0]=0; matr[3][1]=0; matr[3][2]=0; matr[3][3]=1;
}
if (eje=='Y') {
matr[0][0]=cos(ang); matr[0][1]=0; matr[0][2]=-sin(ang); matr[0][3]=0;
matr[1][0]=0; matr[1][1]=1; matr[1][2]=0; matr[1][3]=0;
matr[2][0]=sin(ang); matr[2][1]=0; matr[2][2]=cos(ang); matr[2][3]=0;
matr[3][0]=0; matr[3][1]=0; matr[3][2]=0; matr[3][3]=1;
}
if (eje=='Z') {
matr[0][0]=cos(ang); matr[0][1]=sin(ang); matr[0][2]=0; matr[0][3]=0;
matr[1][0]=-sin(ang); matr[1][1]=cos(ang); matr[1][2]=0; matr[1][3]=0;
matr[2][0]=0; matr[2][1]=0; matr[2][2]=1; matr[2][3]=0;
matr[3][0]=0; matr[3][1]=0; matr[3][2]=0; matr[3][3]=1;
}
}
int main(int argc, char *argv[])
{
int gdriver=DETECT, gmode, errorcode;
int i, j, k, ni, nj, nf, np, ne, nv, pol[128], *id;
char *pv, linea[256];
FILE *fi;
ELEM *el, *ve;
float *x, *y, *z, p[4], q[4];
float xmin, xmax, ymin, ymax, zmin, zmax, xc, yc, zc;
float e, xm, ym, angx, angy, angz, *xp, *yp, *zp;
if (argc !=2) {
fprintf(stderr, "uso: obj fich.geo\n");
exit(1);
}
matp[0][0]=1; matp[0][1]=0; matp[0][2]=0; matp[0][3]=0;
matp[1][0]=0; matp[1][1]=1; matp[1][2]=0; matp[1][3]=0;
matp[2][0]=0; matp[2][1]=0; matp[2][2]=1; matp[2][3]=0;
matp[3][0]=0; matp[3][1]=0; matp[3][2]=0; matp[3][3]=1;
if ((fi=fopen(argv[1], "r"))==NULL) {
fprintf(stderr, "error: no puedo abrir %s\n", argv[1]);
exit(2);
}
fscanf(fi, "%d %d %d", &np, &ne, &nv);
clrscr();
printf("Ang X: "); scanf("%f", &angx);
printf("Ang Y: "); scanf("%f", &angy);
printf("Ang Z: "); scanf("%f", &angz);
/* coordenadas originales */
x=(float *) calloc (np, sizeof (float));
y=(float *) calloc (np, sizeof (float));
z=(float *) calloc (np, sizeof (float));
/* coordenadas proyectadas */
xp=(float *) calloc (np, sizeof (float));
yp=(float *) calloc (np, sizeof (float));
zp=(float *) calloc (np, sizeof (float));
/* vector de elementos */
ve=(ELEM *) calloc (ne, sizeof (ELEM));
id=(int *) calloc(ne, sizeof (int));
rota('X', angx); mmat(matr, matp);
rota('Y', angy); mmat(matr, matp);
rota('Z', angz); mmat(matr, matp);
xmin = ymin = zmin = 999999.;
xmax = ymax = zmax = -xmin;
for (i=0;i<np;i++) {
fscanf (fi, "%f%f%f\n", &x[i], &y[i], &z[i]);
p[0]=x[i]; p[1]=y[i]; p[2]=z[i]; p[3]=1.;
proyecta (p, q);
xp[i]=q[0]; yp[i]=q[1]; zp[i]=q[2];
xmin = min(xmin, xp[i]);
xmax = max(xmax, xp[i]);
ymin = min(ymin, yp[i]);
ymax = max(ymax, yp[i]);
zmin = min(zmin, zp[i]);
zmax = max(zmax, zp[i]);
}
xc = 0.5 * (xmin+xmax);
yc = 0.5 * (ymin+ymax);
zc = 0.5 * (zmin+zmax);
/* initialize graphics and local variables */
initgraph(&gdriver, &gmode, "");
/* read result of initialization */
errorcode=graphresult();
/* an error occurred */
if (errorcode !=grOk) {
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Press any key to halt:");
getch();
exit(1);
}
setcolor(getmaxcolor());
xm = 0.5 * (getmaxx() + 1);
ym = 0.5 * (getmaxy() + 1);
e = 1.5 * min(xm/(xmax-xmin), ym/(ymax-ymin));
for (i=0;i<ne;i++) {
fgets(linea, 256, fi);
pv=strtok(linea, " ");
sscanf(pv, "%d", &nv);
ve[i].nv = nv;
id[i]=i;
ve[i].v = (int *) calloc (nv, sizeof (int));
for (j=0;j<nv;j++) {
pv=strtok(NULL, " ");
sscanf(pv, "%d", &ni); ni--;
ve[i].v[j] = ni;
}
}
fclose(fi);
for (i=0;i<ne;i++) {
el = &ve[i];
ni = el->v[0];
el->z = zp[ni];
for (j=1;j<el->nv;j++) {
nj = el->v[j];
line (xm + (xp[ni]-xc)*e, ym - (yp[ni]-yc)*e,
xm + (xp[nj]-xc)*e, ym - (yp[nj]-yc)*e);
ni = nj;
el->z += zp[ni];
}
el->z /= el->nv;
nj = el->v[0];
line (xm + (xp[ni]-xc)*e, ym - (yp[ni]-yc)*e,
xm + (xp[nj]-xc)*e, ym - (yp[nj]-yc)*e);
}
getch();
for (i=0;i<ne;i++)
for (j=i;j<ne;j++)
if (ve[id[i]].z > ve[id[j]].z) {
k = id[i];
id[i] = id[j];
id[j] = k;
}
for (i=0;i<ne;i++) {
el = &ve[id[i]];
for (j=0, k=0;j<el->nv;j++) {
ni = el->v[j];
pol[k++] = xm + (xp[ni]-xc)*e;
pol[k++] = ym - (yp[ni]-yc)*e;
}
setfillstyle (SOLID_FILL, getbkcolor());
fillpoly(el->nv, pol);
}
getch(); /* clean up */
closegraph();
return 0;
}