/** * Render one triangle of a shield hit effect on one ship. * Each frame, the triangle needs to be rotated into global coords. * * @param trip pointer to triangle in global array * @param orient orientation of object shield is associated with * @param pos center point of object * @param r Red colour * @param g Green colour * @param b Blue colour */ void render_shield_triangle(gshield_tri *trip, matrix *orient, vec3d *pos, ubyte r, ubyte g, ubyte b) { int j; vec3d pnt; vertex *verts[3]; vertex points[3]; if (trip->trinum == -1) return; // Means this is a quad, must have switched detail_level. for (j=0; j<3; j++ ) { // Rotate point into world coordinates vm_vec_unrotate(&pnt, &trip->verts[j].pos, orient); vm_vec_add2(&pnt, pos); // Pnt is now the x,y,z world coordinates of this vert. // For this example, I am just drawing a sphere at that point. if (!Cmdline_nohtl) g3_transfer_vertex(&points[j],&pnt); else g3_rotate_vertex(&points[j], &pnt); points[j].texture_position.u = trip->verts[j].u; points[j].texture_position.v = trip->verts[j].v; Assert((trip->verts[j].u >= 0.0f) && (trip->verts[j].u <= UV_MAX)); Assert((trip->verts[j].v >= 0.0f) && (trip->verts[j].v <= UV_MAX)); verts[j] = &points[j]; } verts[0]->r = r; verts[0]->g = g; verts[0]->b = b; verts[1]->r = r; verts[1]->g = g; verts[1]->b = b; verts[2]->r = r; verts[2]->g = g; verts[2]->b = b; vec3d norm; Poly_count++; vm_vec_perp(&norm,&verts[0]->world,&verts[1]->world,&verts[2]->world); int flags=TMAP_FLAG_TEXTURED | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD; if (!Cmdline_nohtl) flags |= TMAP_HTL_3D_UNLIT; if ( vm_vec_dot(&norm,&verts[1]->world ) >= 0.0 ) { vertex *vertlist[3]; vertlist[0] = verts[2]; vertlist[1] = verts[1]; vertlist[2] = verts[0]; g3_draw_poly( 3, vertlist, flags); } else { g3_draw_poly( 3, verts, flags); } }
void render_low_detail_shield_bitmap(gshield_tri *trip, matrix *orient, vec3d *pos, ubyte r, ubyte g, ubyte b) { int j; vec3d pnt; vertex verts[4]; for (j=0; j<4; j++ ) { // Rotate point into world coordinates vm_vec_unrotate(&pnt, &trip->verts[j].pos, orient); vm_vec_add2(&pnt, pos); // Pnt is now the x,y,z world coordinates of this vert. if(!Cmdline_nohtl) g3_transfer_vertex(&verts[j], &pnt); else g3_rotate_vertex(&verts[j], &pnt); verts[j].texture_position.u = trip->verts[j].u; verts[j].texture_position.v = trip->verts[j].v; } verts[0].r = r; verts[0].g = g; verts[0].b = b; verts[1].r = r; verts[1].g = g; verts[1].b = b; verts[2].r = r; verts[2].g = g; verts[2].b = b; verts[3].r = r; verts[3].g = g; verts[3].b = b; vec3d norm; vm_vec_perp(&norm, &trip->verts[0].pos, &trip->verts[1].pos, &trip->verts[2].pos); vertex *vertlist[4]; if ( vm_vec_dot(&norm, &trip->verts[1].pos ) < 0.0 ) { vertlist[0] = &verts[3]; vertlist[1] = &verts[2]; vertlist[2] = &verts[1]; vertlist[3] = &verts[0]; g3_draw_poly( 4, vertlist, TMAP_FLAG_TEXTURED | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_HTL_3D_UNLIT); } else { vertlist[0] = &verts[0]; vertlist[1] = &verts[1]; vertlist[2] = &verts[2]; vertlist[3] = &verts[3]; g3_draw_poly( 4, vertlist, TMAP_FLAG_TEXTURED | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_HTL_3D_UNLIT); } }
//like g3_draw_poly(), but checks to see if facing. If surface normal is //NULL, this routine must compute it, which will be slow. It is better to //pre-compute the normal, and pass it to this function. When the normal //is passed, this function works like g3_check_normal_facing() plus //g3_draw_poly(). //returns -1 if not facing, 1 if off screen, 0 if drew bool g3_check_and_draw_poly(int nv,g3s_point **pointlist,vms_vector *norm,vms_vector *pnt) { if (do_facing_check(norm,pointlist,pnt)) return g3_draw_poly(nv,pointlist); else return 255; }
//draw a polygon that is always facing you //returns 1 if off screen, 0 if drew bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) { if (calc_rod_corners(bot_point,bot_width,top_point,top_width)) return 0; return g3_draw_poly(4,rod_point_list); }
void draw_face( vertex *v1, vertex *v2, vertex *v3 ) { vec3d norm; vertex *vertlist[3]; vm_vec_perp(&norm,&v1->world, &v2->world, &v3->world); if ( vm_vec_dot(&norm, &v1->world ) >= 0.0 ) { vertlist[0] = v3; vertlist[1] = v2; vertlist[2] = v1; } else { vertlist[0] = v1; vertlist[1] = v2; vertlist[2] = v3; } g3_draw_poly( 3, vertlist, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT ); }
//calls the object interpreter to render an object. The object renderer //is really a seperate pipeline. returns true if drew bool g3_draw_polygon_model(ubyte *p,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,g3s_lrgb model_light,fix *glow_values) { glow_num = -1; //glow off by default while (w(p) != OP_EOF) switch (w(p)) { case OP_DEFPOINTS: { int n = w(p+2); rotate_point_list(Interp_point_list,vp(p+4),n); p += n*sizeof(struct vms_vector) + 4; break; } case OP_DEFP_START: { int n = w(p+2); int s = w(p+4); rotate_point_list(&Interp_point_list[s],vp(p+8),n); p += n*sizeof(struct vms_vector) + 8; break; } case OP_FLATPOLY: { int nv = w(p+2); Assert( nv < MAX_POINTS_PER_POLY ); if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) { int i; #ifdef FADE_FLATPOLY short c; unsigned char cc; int l; #endif // DPH: Now we treat this color as 15bpp // gr_setcolor(w(p+28)); #ifndef FADE_FLATPOLY gr_setcolor(gr_find_closest_color_15bpp(w(p + 28))); #else //l = (32 * model_light) >> 16; l = f2i(fixmul(i2f(32), (model_light.r+model_light.g+model_light.b)/3)); if (l<0) l = 0; else if (l>32) l = 32; cc = gr_find_closest_color_15bpp(w(p+28)); c = gr_fade_table[(l<<8)|cc]; gr_setcolor(c); #endif for (i=0;i<nv;i++) point_list[i] = Interp_point_list + wp(p+30)[i]; g3_draw_poly(nv,point_list); } p += 30 + ((nv&~1)+1)*2; break; } case OP_TMAPPOLY: { int nv = w(p+2); g3s_uvl *uvl_list; Assert( nv < MAX_POINTS_PER_POLY ); if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) { int i; g3s_lrgb light, *lrgb_list; MALLOC(lrgb_list, g3s_lrgb, nv); //calculate light from surface normal if (glow_num < 0) //no glow { light.r = light.g = light.b = -vm_vec_dot(&View_matrix.fvec,vp(p+16)); light.r = f1_0/4 + (light.r*3)/4; light.r = fixmul(light.r,model_light.r); light.g = f1_0/4 + (light.g*3)/4; light.g = fixmul(light.g,model_light.g); light.b = f1_0/4 + (light.b*3)/4; light.b = fixmul(light.b,model_light.b); } else //yes glow { light.r = light.g = light.b = glow_values[glow_num]; glow_num = -1; } //now poke light into l values uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); for (i=0;i<nv;i++) { uvl_list[i].l = (light.r+light.g+light.b)/3; lrgb_list[i].r = light.r; lrgb_list[i].g = light.g; lrgb_list[i].b = light.b; } for (i=0;i<nv;i++) point_list[i] = Interp_point_list + wp(p+30)[i]; g3_draw_tmap(nv,point_list,uvl_list,lrgb_list,model_bitmaps[w(p+28)]); d_free(lrgb_list); } p += 30 + ((nv&~1)+1)*2 + nv*12; break; } case OP_SORTNORM: if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing //draw back then front g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); } else { //not facing. draw front then back g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); } p += 32; break; case OP_RODBM: { g3s_point rod_bot_p,rod_top_p; g3s_lrgb rodbm_light = { f1_0, f1_0, f1_0 }; g3_rotate_point(&rod_bot_p,vp(p+20)); g3_rotate_point(&rod_top_p,vp(p+4)); g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),rodbm_light); p+=36; break; } case OP_SUBCALL: { vms_angvec *a; if (anim_angles) a = &anim_angles[w(p+2)]; else a = &zero_angles; g3_start_instance_angles(vp(p+4),a); g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values); g3_done_instance(); p += 20; break; } case OP_GLOW: if (glow_values) glow_num = w(p+2); p += 4; break; default: Error("invalid polygon model\n"); } return 1; }
//calls the object interpreter to render an object. The object renderer //is really a seperate pipeline. returns true if drew bool g3_draw_polygon_model(void *model_ptr, grs_bitmap **model_bitmaps, vms_angvec *anim_angles, fix model_light, fix *glow_values) { ubyte *p = (ubyte*)model_ptr; int current_poly = 0; glow_num = -1; //glow off by default while (w(p) != OP_EOF) switch (w(p)) { case OP_DEFPOINTS: { int n = w(p + 2); rotate_point_list(Interp_point_list, vp(p + 4), n); p += n*sizeof(struct vms_vector) + 4; break; } case OP_DEFP_START: { int n = w(p + 2); int s = w(p + 4); rotate_point_list(&Interp_point_list[s], vp(p + 8), n); p += n*sizeof(struct vms_vector) + 8; break; } case OP_FLATPOLY: { int nv = w(p + 2); Assert(nv < MAX_POINTS_PER_POLY); if (g3_check_normal_facing(vp(p + 4), vp(p + 16)) > 0) { int i; gr_setcolor(w(p + 28)); for (i = 0; i<nv; i++) point_list[i] = Interp_point_list + wp(p + 30)[i]; g3_draw_poly(nv, point_list); } p += 30 + ((nv&~1) + 1) * 2; break; } case OP_TMAPPOLY: { int nv = w(p + 2); g3s_uvl *uvl_list; Assert(nv < MAX_POINTS_PER_POLY); if (g3_check_normal_facing(vp(p + 4), vp(p + 16)) > 0) { int i; fix light; //calculate light from surface normal if (glow_num < 0) { //no glow light = -vm_vec_dot(&View_matrix.fvec, vp(p + 16)); light = f1_0 / 4 + (light * 3) / 4; light = fixmul(light, model_light); } else { //yes glow light = glow_values[glow_num]; glow_num = -1; } //now poke light into l values uvl_list = (g3s_uvl *)(p + 30 + ((nv&~1) + 1) * 2); for (i = 0; i<nv; i++) uvl_list[i].l = light; for (i = 0; i<nv; i++) point_list[i] = Interp_point_list + wp(p + 30)[i]; g3_draw_tmap(nv, point_list, uvl_list, model_bitmaps[w(p + 28)]); } p += 30 + ((nv&~1) + 1) * 2 + nv * 12; break; } case OP_SORTNORM: if (g3_check_normal_facing(vp(p + 16), vp(p + 4)) > 0) { //facing //draw back then front g3_draw_polygon_model(p + w(p + 30), model_bitmaps, anim_angles, model_light, glow_values); g3_draw_polygon_model(p + w(p + 28), model_bitmaps, anim_angles, model_light, glow_values); } else { //not facing. draw front then back g3_draw_polygon_model(p + w(p + 28), model_bitmaps, anim_angles, model_light, glow_values); g3_draw_polygon_model(p + w(p + 30), model_bitmaps, anim_angles, model_light, glow_values); } p += 32; break; case OP_RODBM: { g3s_point rod_bot_p, rod_top_p; g3_rotate_point(&rod_bot_p, vp(p + 20)); g3_rotate_point(&rod_top_p, vp(p + 4)); g3_draw_rod_tmap(model_bitmaps[w(p + 2)], &rod_bot_p, w(p + 16), &rod_top_p, w(p + 32), f1_0); p += 36; break; } case OP_SUBCALL: { vms_angvec *a; if (anim_angles) a = &anim_angles[w(p + 2)]; else a = &zero_angles; g3_start_instance_angles(vp(p + 4), a); g3_draw_polygon_model(p + w(p + 16), model_bitmaps, anim_angles, model_light, glow_values); g3_done_instance(); p += 20; break; } case OP_GLOW: if (glow_values) glow_num = w(p + 2); p += 4; break; default: Int3(); } return 1; }