#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 #F88484", "+ c #F68181", "@ c #EF7878", "# c #D15151", "$ c #B12828", "% c #970606", "& c #F78282", "* c #E76D6D", "= c #C74545", "- c #A71B1B", "; c #960404", "> c #EC7575", ", c #D65858", "' c #B42D2D", ") c #9E1010", "! c #930202", "~ c #FB4242", "{ c #FA5252", "] c #FA5858", "^ c #EE5858", "/ c #D74A4A", "( c #FE1212", "_ c #FD2121", ": c #FC2C2C", "< c #E42C2C", "[ c #C11E1E", "} c #FF0000", "| c #DB0000", "1 c #B70101", "2 c #BB0101", "3 c #C10101", " .........+@#$%", " ..........&*=-;", " ...........>,')!", " ...........>,')!!", " ...........>,')!!!", " ~{]]]]]]]]]^/')!!!!", "(_::::::::::<[)!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!!!", "}}}}}}}}}}}}|1!!!!! ", "}}}}}}}}}}}}|1!!!! ", "}}}}}}}}}}}}|1!!! ", "}}}}}}}}}}}}|1!! ", "}}}}}}}}}}}}|2! ", "}}}}}}}}}}}}|3 " }; gchar *module_name = "The gouraud 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); } /************************************************************************* * rendering_func **************************************************************************/ GdkPixmap *rendering_func(GtkWidget *area, gint width, gint height) { GdkPixmap *pixmap; FrameStruct *frame; GSList *tmp_list, *tmp_ls; ObjectStruct *Tmp; TriangleListStruct *TmpTri; CameraStruct *camera; Vector P1, P2, P3; gdouble color[3], distance[3]; gdouble color_result[3]; int max_triangles; int nbTri; Triangle2DNormCol *TabTri; LightSourceStruct *Light; Vector NormalLight; gdouble Norme, alpha; gdouble *Zbuffer; gint i, j; guchar *rgb_buf; 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(Triangle2DNormCol, 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) { persp_3d_to_2d(frame, TmpTri->P1, P1, width, height); persp_3d_to_2d(frame, TmpTri->P2, P2, width, height); persp_3d_to_2d(frame, TmpTri->P3, P3, width, height); if (nbTri >= max_triangles) { max_triangles *= 2; TabTri = g_renew(Triangle2DNormCol, TabTri, max_triangles); } TabTri[nbTri].P[0][0] = P1[0]; TabTri[nbTri].P[0][1] = P1[1]; TabTri[nbTri].P[1][0] = P2[0]; TabTri[nbTri].P[1][1] = P2[1]; TabTri[nbTri].P[2][0] = P3[0]; TabTri[nbTri].P[2][1] = P3[1]; /* Calcul des distances des trois sommets a la camera */ /* first vertex */ distance[0] = camera->Location[0]-TmpTri->P1[0]; distance[1] = camera->Location[1]-TmpTri->P1[1]; distance[2] = camera->Location[2]-TmpTri->P1[2]; TabTri[nbTri].Distance[0] = V3DLength(distance); /* second vertex */ distance[0] = camera->Location[0]-TmpTri->P2[0]; distance[1] = camera->Location[1]-TmpTri->P2[1]; distance[2] = camera->Location[2]-TmpTri->P2[2]; TabTri[nbTri].Distance[1] = V3DLength(distance); /* third vertex */ distance[0] = camera->Location[0]-TmpTri->P3[0]; distance[1] = camera->Location[1]-TmpTri->P3[1]; distance[2] = camera->Location[2]-TmpTri->P3[2]; TabTri[nbTri].Distance[2] = V3DLength(distance); /* Calcul des couleurs des trois sommets */ /* 1er sommet */ 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) 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]; } } color_result[0] = CLAMP(color_result[0], 0.0, 1.0); color_result[1] = CLAMP(color_result[1], 0.0, 1.0); color_result[2] = CLAMP(color_result[2], 0.0, 1.0); TabTri[nbTri].Color[0][0] = color_result[0]; TabTri[nbTri].Color[0][1] = color_result[1]; TabTri[nbTri].Color[0][2] = color_result[2]; /* 2nd vertex */ 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->P2[0]; NormalLight[1] = Light->Location[1]-TmpTri->P2[1]; NormalLight[2] = Light->Location[2]-TmpTri->P2[2]; Norme = V3DLength(NormalLight); NormalLight[0] /= Norme; NormalLight[1] /= Norme; NormalLight[2] /= Norme; if (Tmp->Texture && Tmp->Texture->finish) alpha = V3DDot(TmpTri->N2, NormalLight) * Tmp->Texture->finish->diffuse; else alpha = V3DDot(TmpTri->N2, NormalLight) * 0.6; if (Tmp->Type == PLANE_OBJECT) 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]; } } color_result[0] = CLAMP(color_result[0], 0.0, 1.0); color_result[1] = CLAMP(color_result[1], 0.0, 1.0); color_result[2] = CLAMP(color_result[2], 0.0, 1.0); TabTri[nbTri].Color[1][0] = color_result[0]; TabTri[nbTri].Color[1][1] = color_result[1]; TabTri[nbTri].Color[1][2] = color_result[2]; /* third vertex */ 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->P3[0]; NormalLight[1] = Light->Location[1]-TmpTri->P3[1]; NormalLight[2] = Light->Location[2]-TmpTri->P3[2]; Norme = V3DLength(NormalLight); NormalLight[0] /= Norme; NormalLight[1] /= Norme; NormalLight[2] /= Norme; if (Tmp->Texture && Tmp->Texture->finish) alpha = V3DDot(TmpTri->N3, NormalLight) * Tmp->Texture->finish->diffuse; else alpha = V3DDot(TmpTri->N3, NormalLight) * 0.6; if (Tmp->Type == PLANE_OBJECT) 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]; } } color_result[0] = CLAMP(color_result[0], 0.0, 1.0); color_result[1] = CLAMP(color_result[1], 0.0, 1.0); color_result[2] = CLAMP(color_result[2], 0.0, 1.0); TabTri[nbTri].Color[2][0] = color_result[0]; TabTri[nbTri].Color[2][1] = color_result[1]; TabTri[nbTri].Color[2][2] = color_result[2]; nbTri++; } } /* if (Tmp->Visible) */ } /* Displaying */ Zbuffer = g_new(double, width * height); for (i=0 ; istyle->white_gc, 0,0, width, height, GDK_RGB_DITHER_MAX, rgb_buf, 3*width); /* Freeing ... */ g_free(rgb_buf); g_free(TabTri); g_free(Zbuffer); return pixmap; }