/* render_hiddenfaces.c * Giram - A GPLed Modelling Program. * Copyright (C) 1999-2002 DindinX * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include #include #include #include "src/giram.h" #include "src/object.h" #include "src/camera.h" gchar *module_icon_xpm[] = { "20 20 2 1", " c None", ". c #000000", " .............", " . ..", " . . .", " . . .", " . . .", " . . .", " ............. .", " . . .", " . . .", " . . .", " . . .", " . . .", " . . . ", " . . . ", " . . . ", " . . . ", " . .. ", " ............. ", " ", " " }; gchar *module_name = "The hiddenfaces renderer module"; gint module_type = 1; /***************************************************************************** * persp_3d_to_2d ******************************************************************************/ static void persp_3d_to_2d(FrameStruct *frame, Vector Point3d, Vector Point2d, int width, int height) { double xd,yd,zd; double norme; double vd,v0,t; double RiX, RiY, RiZ; double Ka, Kb; double u,v; CameraStruct *Camera; Camera = frame->all_cameras->data; xd = Point3d[0] - Camera->Location[0]; yd = Point3d[1] - Camera->Location[1]; zd = Point3d[2] - Camera->Location[2]; norme = sqrt(xd*xd+yd*yd+zd*zd); xd=xd / norme; yd=yd / norme; zd=zd / norme; vd = Camera->A*xd+Camera->B*yd+Camera->C*zd; if (fabs(vd)<1e-6) vd = 1e-6; v0 = -(Camera->A*Camera->x0+Camera->B*Camera->y0+Camera->C*Camera->z0+ Camera->D); t = v0 / vd; RiX = Camera->Location[0]+xd*t; RiY = Camera->Location[1]+yd*t; RiZ = Camera->Location[2]+zd*t; if (fabs(Camera->Du2)<=1e-6) { u=(Camera->Nc[0]*RiX+Camera->Nc[1]*RiY+Camera->Nc[2]*RiZ-Camera->Du0)/ (Camera->Du1-Camera->Na[0]*RiX-Camera->Na[1]*RiY-Camera->Na[2]*RiZ); } else { Ka = Camera->Dux + (Camera->Qux[0]*RiX+Camera->Qux[1]*RiY+Camera->Qux[2]*RiZ); Kb = Camera->Duy + (Camera->Quy[0]*RiX+Camera->Quy[1]*RiY+Camera->Quy[2]*RiZ); u = Ka - sqrt(Ka*Ka-Kb); if ((u>1.0) || (u<0.0)) u = Ka + sqrt(Ka*Ka-Kb); } if (fabs(Camera->Dv2)<=1e-6) { v=(Camera->Nb[0]*RiX+Camera->Nb[1]*RiY+Camera->Nb[2]*RiZ-Camera->Dv0)/ (Camera->Dv1-Camera->Na[0]*RiX-Camera->Na[1]*RiY-Camera->Na[2]*RiZ); } else { Ka = Camera->Dvx + (Camera->Qvx[0]*RiX+Camera->Qvx[1]*RiY+Camera->Qvx[2]*RiZ); Kb = Camera->Dvy + (Camera->Qvy[0]*RiX+Camera->Qvy[1]*RiY+Camera->Qvy[2]*RiZ); v = Ka - sqrt(Ka*Ka-Kb); if ((v>1.0) || (v<0.0)) v = Ka + sqrt(Ka*Ka-Kb); } Point2d[0]=(u*width); Point2d[1]=((1.0-v)*height); } static int local_comparTri(const void *Tri1, const void *Tri2) { return (((Triangle2D *)Tri2)->distance - ((Triangle2D *)Tri1)->distance); } /************************************************************************* * rendering_func **************************************************************************/ GdkPixmap *rendering_func(GtkWidget *area, gint width, gint height) { GdkPixmap *pixmap; FrameStruct *frame; ObjectStruct *Tmp; GSList *tmp_list; TriangleListStruct *TmpTri; Triangle2D *TabTri; int nbTri; register int i; GdkPoint points[3]; int max_triangles; Vector Vect; CameraStruct *Camera; pixmap = gdk_pixmap_new(area->window, width, height, -1); gdk_draw_rectangle(pixmap, area->style->black_gc, TRUE, 0, 0, width, height); frame = g_object_get_data(G_OBJECT(area), "frame"); Camera = frame->all_cameras->data; nbTri = 0; max_triangles = 256; TabTri = g_new(Triangle2D, max_triangles); for (tmp_list = frame->all_objects ; tmp_list ; tmp_list = g_slist_next(tmp_list)) { Tmp = tmp_list->data; if (Tmp->visible) { for (TmpTri = Tmp->FirstTriangle ; TmpTri ; TmpTri = TmpTri->Next) { if (nbTri >= max_triangles) { max_triangles *= 2; TabTri = g_realloc(TabTri, max_triangles*sizeof(Triangle2D)); } persp_3d_to_2d(frame, TmpTri->P1, TabTri[nbTri].P1, width, height); persp_3d_to_2d(frame, TmpTri->P2, TabTri[nbTri].P2, width, height); persp_3d_to_2d(frame, TmpTri->P3, TabTri[nbTri].P3, width, height); Vect[0]=TmpTri->P1[0]+TmpTri->P2[0]+TmpTri->P3[0]-3.0*Camera->Location[0]; Vect[1]=TmpTri->P1[1]+TmpTri->P2[1]+TmpTri->P3[1]-3.0*Camera->Location[1]; Vect[2]=TmpTri->P1[2]+TmpTri->P2[2]+TmpTri->P3[2]-3.0*Camera->Location[2]; TabTri[nbTri].distance = V3DLength(Vect); nbTri++; } } /* if (Tmp->visible) */ } /* Sorting ... */ qsort(TabTri, nbTri, sizeof(Triangle2D), local_comparTri); /* Displaying */ for (i=0 ; istyle->black_gc, TRUE, points, 3); gdk_draw_line(pixmap, area->style->white_gc, points[0].x, points[0].y, points[1].x, points[1].y); gdk_draw_line(pixmap, area->style->white_gc, points[1].x, points[1].y, points[2].x, points[2].y); gdk_draw_line(pixmap, area->style->white_gc, points[2].x, points[2].y, points[0].x, points[0].y); } /* Freeing ... */ g_free(TabTri); return pixmap; }