/* render_flat.c * Giram - A GPLed Modelling Program. * Copyright (C) 2002 David Odin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; 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 32 1", " c None", ". c #FD5757", "+ c #FE5858", "@ c #FE5757", "# c #FB5454", "$ c #E73F3F", "% c #B80C0C", "& c #E94141", "* c #C11515", "= c #AF0202", "- c #FD5656", "; c #AD0000", "> c #FD4343", ", c #FD4848", "' c #FE4949", ") c #FE4848", "! c #F23F3F", "~ c #C31515", "{ c #FD0202", "] c #FD0B0B", "^ c #FE0D0D", "/ c #FE0E0E", "( c #F00B0B", "_ c #BA0202", ": c #FD0000", "< c #FE0000", "[ c #F00000", "} c #BA0000", "| c #AC0000", "1 c #F20000", "2 c #BF0000", "3 c #FA0000", " ..+++++++@#$%", " ..+++++++@#&*=", " .-@++++++@#&*=;", " .-@++++++@#&*=;;", " .-@@@@@@@@#&*=;;;", " >,'''''''')!~=;;;;", " {]^////////^(_;;;;;", " ::<<<<<<<<<<[};;;;;", " ::<<<<<<<<<<[};;;;;", " ::<<<<<<<<<<[};;;;;", " ::<<<<<<<<<<[};;;;|", " ::<<<<<<<<<<[};;;||", " ::<<<<<<<<<<[};;|; ", " ::<<<<<<<<<<[};|; ", " ::<<<<<<<<<<[}|; ", " ::<<<<<<<<<<[}; ", " ::::::::::::12 ", " ::::::::::::3 ", " ", " " }; gchar *module_name = "The flat shaded 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); } typedef struct Triangle2Dflat { Vector P1,P2,P3; gdouble distance; gdouble color[3]; } Triangle2Dflat; static int comparTriflat(const void *Tri1, const void *Tri2) { return (((Triangle2Dflat *)Tri2)->distance - ((Triangle2Dflat *)Tri1)->distance); } /************************************************************************* * rendering_func **************************************************************************/ GdkPixmap *rendering_func(GtkWidget *area, gint width, gint height) { GdkPixmap *pixmap; FrameStruct *frame; GSList *tmp_list, *tmp_ls; ObjectStruct *Tmp; TriangleListStruct *TmpTri; Vector Vect, NormalLight; Triangle2Dflat *TabTri; CameraStruct *Camera; gint nbTri, max_triangles, i; GdkPoint points[3]; gdouble color[3], color_result[3]; LightSourceStruct *Light; gdouble Norme, alpha; GdkGC *gc; GdkColormap *colormap; GdkColor gdk_color; gc = gdk_gc_new(area->window); colormap = gdk_drawable_get_colormap(area->window); 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(Triangle2Dflat, max_triangles); for (tmp_list = frame->all_objects ; tmp_list ; tmp_list = g_slist_next(tmp_list)) { Tmp = tmp_list->data; if (Tmp->visible) { if (Tmp->Texture && Tmp->Texture->Pigment && Tmp->Texture->Pigment->Color) { color[0] = Tmp->Texture->Pigment->Color[0]; color[1] = Tmp->Texture->Pigment->Color[1]; color[2] = Tmp->Texture->Pigment->Color[2]; } else { color[0] = color[1] = color[2] = 1.0; } for (TmpTri = Tmp->FirstTriangle ; TmpTri ; TmpTri = TmpTri->Next) { if (nbTri >= max_triangles) { max_triangles *= 2; TabTri = g_realloc(TabTri, max_triangles*sizeof(Triangle2Dflat)); } 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); if (Tmp->Texture && Tmp->Texture->finish) { color_result[0] = color[0] * Tmp->Texture->finish->ambient[0]; color_result[1] = color[1] * Tmp->Texture->finish->ambient[1]; color_result[2] = color[2] * Tmp->Texture->finish->ambient[2]; } else { color_result[0] = color[0] * 0.1; color_result[1] = color[1] * 0.1; color_result[2] = color[2] * 0.1; } for (tmp_ls = frame->all_light_sources ; tmp_ls ; tmp_ls = g_slist_next(tmp_ls) ) { Light = tmp_ls->data; NormalLight[0] = Light->Location[0]-TmpTri->P1[0]; NormalLight[1] = Light->Location[1]-TmpTri->P1[1]; NormalLight[2] = Light->Location[2]-TmpTri->P1[2]; Norme = V3DLength(NormalLight); NormalLight[0] /= Norme; NormalLight[1] /= Norme; NormalLight[2] /= Norme; if (Tmp->Texture && Tmp->Texture->finish) alpha = V3DDot(TmpTri->N1, NormalLight) * Tmp->Texture->finish->diffuse; else alpha = V3DDot(TmpTri->N1, NormalLight) * 0.6; if (Tmp->Type == PLANE_OBJECT) /* FIXME */ alpha = fabs(alpha); if (alpha > 0.0) { color_result[0] += alpha*color[0]*Light->Color[0]; color_result[1] += alpha*color[1]*Light->Color[1]; color_result[2] += alpha*color[2]*Light->Color[2]; } } TabTri[nbTri].color[0] = CLAMP(color_result[0], 0.0, 1.0); TabTri[nbTri].color[1] = CLAMP(color_result[1], 0.0, 1.0); TabTri[nbTri].color[2] = CLAMP(color_result[2], 0.0, 1.0); nbTri++; } } /* if (Tmp->Visible) */ } /* Sorting ... */ qsort(TabTri, nbTri, sizeof(Triangle2Dflat), comparTriflat); /* Displaying */ for (i=0 ; i