/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ /* * $Logfile: /Freespace2/code/Render/3ddraw.cpp $ * $Revision: 2.52.2.2 $ * $Date: 2006-10-06 10:03:02 $ * $Author: taylor $ * * 3D rendering primitives * * $Log: not supported by cvs2svn $ * Revision 2.52.2.1 2006/08/19 04:38:47 taylor * maybe optimize the (PI/2), (PI*2) and (RAND_MAX/2) stuff a little bit * * Revision 2.52 2006/05/27 16:47:12 taylor * remove some of the old batcher functions, nothing is using them now anyway * minor cleanup * add orient UV flipping to HTL drawing functions, like retail/non-HTL has support for * * Revision 2.51 2006/04/20 06:32:23 Goober5000 * proper capitalization according to Volition * * Revision 2.50 2006/04/12 22:23:41 taylor * compiler warning fixes to make GCC 4.1 shut the hell up * * Revision 2.49 2006/04/12 01:00:58 taylor * some small optimizations and cleanup * use floats for gr_bitmap() size and positions, mainly for non-standard resolutions since this allows proper resizing and positioning * (the cast to float was happening later anyway so there should be not additional slowdown from that with standard resolutions) * change g3_draw_2d_poly_bitmap() to use floats instead of ints, gets rid of the extra cast and allows better resize values * * Revision 2.48 2006/03/18 10:23:46 taylor * make the main vital TMAP_MAX_VERTS stuff dynamic, should handle the major non-HTL related crashes * * Revision 2.47 2006/02/25 21:47:08 Goober5000 * spelling * * Revision 2.46 2005/10/28 14:45:55 taylor * more TMAP_MAX_VERTS overflow protection for non-HTL usage (these are the things that need to be addressed to fix non-HTL) * fix some compiler warning messages * don't do any decal processing if decals are disabled, the math was a waste of CPU cycles in that case * * Revision 2.45 2005/08/25 22:32:55 taylor * since the geomtry_batcher can send more verts than non-HTL code can handle, avoid drawing in that case to avoid crashing * * Revision 2.44 2005/07/18 03:45:09 taylor * more non-standard res fixing * - I think everything should default to resize now (much easier than having to figure that crap out) * - new mouse_get_pos_unscaled() function to return 1024x768/640x480 relative values so we don't have to do it later * - lots of little cleanups which fix several strange offset/size problems * - fix gr_resize/unsize_screen_pos() so that it won't wrap on int (took too long to track this down) * * Revision 2.43 2005/05/12 17:49:16 taylor * use vm_malloc(), vm_free(), vm_realloc(), vm_strdup() rather than system named macros * fixes various problems and is past time to make the switch * * Revision 2.42 2005/04/24 12:56:43 taylor * really are too many changes here: * - remove all bitmap section support and fix problems with previous attempt * ( code/bmpman/bmpman.cpp, code/bmpman/bmpman.h, code/globalincs/pstypes.h, * code/graphics/2d.cpp, code/graphics/2d.h code/graphics/grd3dbmpman.cpp, * code/graphics/grd3dinternal.h, code/graphics/grd3drender.cpp, code/graphics/grd3dtexture.cpp, * code/graphics/grinternal.h, code/graphics/gropengl.cpp, code/graphics/gropengl.h, * code/graphics/gropengllight.cpp, code/graphics/gropengltexture.cpp, code/graphics/gropengltexture.h, * code/graphics/tmapper.h, code/network/multi_pinfo.cpp, code/radar/radarorb.cpp * code/render/3ddraw.cpp ) * - use CLAMP() define in gropengl.h for gropengllight instead of single clamp() function * - remove some old/outdated code from gropengl.cpp and gropengltexture.cpp * * Revision 2.41 2005/04/24 02:40:40 wmcoolmon * Lowlevel (ie vertex buffer-mapping) functions for _rect and _shade * * Revision 2.40 2005/04/12 05:26:37 taylor * many, many compiler warning and header fixes (Jens Granseuer) * fix free on possible NULL in modelinterp.cpp (Jens Granseuer) * * Revision 2.39 2005/04/05 05:53:23 taylor * s/vector/vec3d/g, better support for different compilers (Jens Granseuer) * * Revision 2.38 2005/03/25 22:36:01 Goober5000 * removed unreferenced variable * --Goober5000 * * Revision 2.37 2005/03/23 20:08:33 phreak * Some specular values in g3_draw_perspective_bitmap() were being incorrectly set. fixed that * * Revision 2.36 2005/03/20 00:11:27 phreak * high-level implementation for gr_draw_htl_line and gr_draw_htl_sphere * * Revision 2.35 2005/03/19 18:02:34 bobboau * added new graphic functions for state blocks * also added a class formanageing a new effect * * Revision 2.34 2005/03/16 01:35:59 bobboau * added a geometry batcher and implemented it in sevral places * namely: lasers, thrusters, and particles, * these have been the primary botle necks for some time, * and this seems to have smoothed them out quite a bit. * * Revision 2.33 2005/03/13 08:38:05 wmcoolmon * Commented out unneeded variables * * Revision 2.32 2005/03/10 15:35:21 bobboau * fixed a local/global conflict * * Revision 2.31 2005/03/10 08:00:13 taylor * change min/max to MIN/MAX to fix GCC problems * add lab stuff to Makefile * build unbreakage for everything that's not MSVC++ 6 * lots of warning fixes * fix OpenGL rendering problem with ship insignias * no Warnings() in non-debug mode for Linux (like Windows) * some campaign savefile fixage to stop reverting everyones data * * Revision 2.30 2005/03/09 03:23:32 bobboau * added a new interface render funtion * * Revision 2.29 2005/03/03 14:29:39 bobboau * fixed a small error from my earlier commit. * * Revision 2.28 2005/03/03 02:39:14 bobboau * added trilist suport to the poly rendering functions * and a gr_bitmap_list function that uses it * * Revision 2.27 2005/03/01 06:55:43 bobboau * oh, hey look I've commited something :D * animation system, weapon models detail box alt-tab bug, probly other stuff * * Revision 2.26 2005/02/18 09:58:40 wmcoolmon * More nonstandard res fixing * * Revision 2.25 2005/02/04 20:06:07 taylor * merge with Linux/OSX tree - p0204-2 * * Revision 2.24 2005/01/28 11:06:22 Goober5000 * changed a bunch of transpose-rotate sequences to use unrotate instead * --Goober5000 * * Revision 2.23 2004/07/26 20:47:50 Kazan * remove MCD complete * * Revision 2.22 2004/07/12 16:33:04 Kazan * MCD - define _MCD_CHECK to use memory tracking * * Revision 2.21 2004/04/26 12:36:10 taylor * add color and HTL support for g3_draw_rod() * * Revision 2.20 2004/04/11 13:56:33 randomtiger * Adding batching functions here and there and into gr_screen for use with OGL when its ready. * * Revision 2.19 2004/04/08 20:13:17 phreak * got rid of some compile warnings * * Revision 2.18 2004/03/06 23:28:24 bobboau * fixed motion debris * animated laser textures * and added a new error check called a safepoint, mostly for tracking the 'Y bug' * * Revision 2.17 2004/03/05 09:01:51 Goober5000 * Uber pass at reducing #includes * --Goober5000 * * Revision 2.16 2004/02/27 04:09:56 bobboau * fixed a Z buffer error in HTL submodel rendering, * and glow points, * and other stuff * * Revision 2.15 2004/02/14 00:18:35 randomtiger * Please note that from now on OGL will only run with a registry set by Launcher v4. See forum for details. * OK, these changes effect a lot of file, I suggest everyone updates ASAP: * Removal of many files from project. * Removal of meanless Gr_bitmap_poly variable. * Removal of glide, directdraw, software modules all links to them, and all code specific to those paths. * Removal of redundant Fred paths that arent needed for Fred OGL. * Have seriously tidied the graphics initialisation code and added generic non standard mode functionality. * Fixed many D3D non standard mode bugs and brought OGL up to the same level. * Removed texture section support for D3D8, voodoo 2 and 3 cards will no longer run under fs2_open in D3D, same goes for any card with a maximum texture size less than 1024. * * Revision 2.14 2004/02/13 04:17:14 randomtiger * Turned off fog in OGL for Fred. * Simulated speech doesnt say tags marked by $ now. * The following are fixes to issues that came up testing TBP in fs2_open and fred2_open: * Changed vm_vec_mag and parse_tmap to fail gracefully on bad data. * Error now given on missing briefing icon and bad ship normal data. * Solved more species divide by zero error. * Fixed neb cube crash. * * Revision 2.13 2004/01/24 14:31:27 randomtiger * Added the D3D particle code, its not bugfree but works perfectly on my card and helps with the framerate. * Its optional and off by default, use -d3d_particle to activiate. * Also bumped up D3D ambient light setting, it was way too dark. * Its now set to something similar to the original game. * * Revision 2.12 2004/01/19 00:56:10 randomtiger * Some more small changes for Fred OGL * * Revision 2.11 2003/11/25 15:04:46 fryday * Got lasers to work in HT&L OpenGL * Messed a bit with opengl_tmapper_internal3d, draw_laser functions, and added draw_laser_htl * * Revision 2.10 2003/11/17 04:25:57 bobboau * made the poly list dynamicly alocated, * started work on fixing the node model not rendering, * but most of that got commented out so I wouldn't have to deal with it * while mucking about with the polylist * * Revision 2.9 2003/11/16 04:09:27 Goober5000 * language * * Revision 2.8 2003/11/11 03:56:12 bobboau * lots of bug fixing, much of it in nebula and bitmap drawing * * Revision 2.7 2003/10/29 18:18:52 randomtiger * D3D particle flicker fix, also fixes explosions and thruster glows * * Revision 2.6 2003/10/23 18:03:24 randomtiger * Bobs changes (take 2) * * Revision 2.5 2003/08/30 14:49:01 phreak * fixed some random specular lighting bugs * * Revision 2.4 2003/08/21 15:03:43 phreak * zeroed out the specular fields since they caused some flickering * * Revision 2.3 2003/03/18 10:07:05 unknownplayer * The big DX/main line merge. This has been uploaded to the main CVS since I can't manage to get it to upload to the DX branch. Apologies to all who may be affected adversely, but I'll work to debug it as fast as I can. * * Revision 2.2.2.1 2002/09/24 18:56:45 randomtiger * DX8 branch commit * * This is the scub of UP's previous code with the more up to date RT code. * For full details check previous dev e-mails * * Revision 2.2 2002/08/06 01:49:08 penguin * Renamed ccode members to cc_or and cc_and * * Revision 2.1 2002/08/01 01:41:09 penguin * The big include file move * * Revision 2.0 2002/06/03 04:02:27 penguin * Warpcore CVS sync * * Revision 1.2 2002/05/04 04:52:22 mharris * 1st draft at porting * * Revision 1.1 2002/05/02 18:03:12 mharris * Initial checkin - converted filenames and includes to lower case * * * 18 9/06/99 3:23p Andsager * Make fireball and weapon expl ani LOD choice look at resolution of the * bitmap * * 17 8/27/99 9:07p Dave * LOD explosions. Improved beam weapon accuracy. * * 16 7/29/99 12:05a Dave * Nebula speed optimizations. * * 15 7/13/99 1:16p Dave * 32 bit support. Whee! * * 14 7/02/99 3:05p Anoop * Oops. Fixed g3_draw_2d_poly() so that it properly handles poly bitmap * and LFB bitmap calls. * * 13 6/29/99 10:35a Dave * Interface polygon bitmaps! Whee! * * 12 6/22/99 7:03p Dave * New detail options screen. * * 11 6/16/99 4:06p Dave * New pilot info popup. Added new draw-bitmap-as-poly function. * * 10 6/08/99 5:17p Dave * Fixed up perspective bitmap drawing. * * 9 6/03/99 6:37p Dave * More TNT fun. Made perspective bitmaps more flexible. * * 8 5/28/99 1:58p Dave * Fixed problem with overwriting bank value drawing perspective bitmaps. * * 7 5/28/99 1:45p Dave * Fixed up perspective bitmap drawing. * * 6 5/24/99 5:45p Dave * Added detail levels to the nebula, with a decent speedup. Split nebula * lightning into its own section. * * 5 4/07/99 6:22p Dave * Fred and FreeSpace support for multiple background bitmaps and suns. * Fixed link errors on all subprojects. Moved encrypt_init() to * cfile_init() and lcl_init(), since its safe to call twice. * * 4 3/09/99 6:24p Dave * More work on object update revamping. Identified several sources of * unnecessary bandwidth. * * 3 2/11/99 3:08p Dave * PXO refresh button. Very preliminary squad war support. * * 2 10/07/98 10:53a Dave * Initial checkin. * * 1 10/07/98 10:51a Dave * * 37 3/22/98 2:34p John * If alpha effects is on lowest detail level, draw rotated bitmaps as * scaled bitmaps. * * 36 3/16/98 4:51p John * Added low-level code to clip all polygons against an arbritary plane. * Took out all old model_interp_zclip and used this new method instead. * * 35 3/04/98 9:29a John * Made rotated bitmaps force all sw's to the same value after clipping. * * 34 3/03/98 6:59p John * * 33 1/26/98 5:12p John * Added in code for Pentium Pro specific optimizations. Speed up * zbuffered correct tmapper about 35%. Speed up non-zbuffered scalers * by about 25%. * * 32 1/15/98 2:16p John * Made bitmaps zbuffer at center minus radius. * Made fireballs sort after objects they are around. * * 31 1/06/98 2:11p John * Made g3_draw_rotated bitmap draw the same orientation as g3_draw_bitmap * (orient=0) and made it be the same size (it was 2x too big before). * * 30 12/30/97 6:44p John * Made g3_Draw_bitmap functions account for aspect of bitmap. * * 29 12/04/97 12:09p John * Made glows use scaler instead of tmapper so they don't rotate. Had to * add a zbuffered scaler. * * 28 12/02/97 4:00p John * Added first rev of thruster glow, along with variable levels of * translucency, which retquired some restructing of palman. * * 27 11/29/97 2:05p John * made g3_draw_bitmap and g3_draw_rotated bitmap take w&h, not w/2 & h/2, * like they used to incorrectly assume. Added code to model to read in * thruster radius's. * * 26 10/20/97 4:49p John * added weapon trails. * added facing bitmap code to 3d lib. * * 25 10/03/97 9:10a John * added better antialiased line drawer * * 24 9/09/97 3:39p Sandeep * warning level 4 bugs * * 23 7/11/97 11:54a John * added rotated 3d bitmaps. * * 22 5/07/97 2:59p John * Initial rev of D3D texturing. * * 21 4/29/97 9:55a John * * 20 3/10/97 2:25p John * Made pofview zbuffer. Made textest work with new model code. Took * out some unnecessary Asserts in the 3d clipper. * * * 19 3/06/97 5:36p Mike * Change vec_normalize_safe() back to vec_normalize(). * Spruce up docking a bit. * * 18 3/06/97 10:56a Mike * Write error checking version of vm_vec_normalize(). * Fix resultant problems. * * 17 2/26/97 5:24p John * Added g3_draw_sphere_ez * * 16 2/17/97 5:18p John * Added a bunch of RCS headers to a bunch of old files that don't have * them. * * $NoKeywords: $ */ #include "render/3dinternal.h" #include "graphics/tmapper.h" #include "physics/physics.h" // For Physics_viewer_bank for g3_draw_rotated_bitmap #include "bmpman/bmpman.h" #include "globalincs/alphacolors.h" #include "cmdline/cmdline.h" #include "graphics/grbatch.h" #include "io/key.h" //vertex buffers for polygon drawing and clipping static vertex **Vbuf0 = NULL; static vertex **Vbuf1 = NULL; static int Num_vbufs_allocated = 0; static void g3_deallocate_vbufs() { if (Vbuf0 != NULL) { vm_free(Vbuf0); Vbuf0 = NULL; } if (Vbuf1 != NULL) { vm_free(Vbuf1); Vbuf1 = NULL; } } static void g3_allocate_vbufs(int nv) { static ubyte dealloc = 0; Assert( nv >= 0 ); Assert( nv || Num_vbufs_allocated ); if (!dealloc) { atexit(g3_deallocate_vbufs); dealloc = 1; } if (nv > Num_vbufs_allocated) { g3_deallocate_vbufs(); Vbuf0 = (vertex**) vm_malloc( nv * sizeof(vertex) ); Vbuf1 = (vertex**) vm_malloc( nv * sizeof(vertex) ); Num_vbufs_allocated = nv; } // make sure everything is valid Verify( Vbuf0 != NULL ); Verify( Vbuf1 != NULL ); } //deal with a clipped line int must_clip_line(vertex *p0,vertex *p1,ubyte codes_or, uint flags) { int ret = 0; clip_line(&p0,&p1,codes_or, flags); if (p0->codes & p1->codes) goto free_points; codes_or = (unsigned char)(p0->codes | p1->codes); if (codes_or & CC_BEHIND) goto free_points; if (!(p0->flags&PF_PROJECTED)) g3_project_vertex(p0); if (p0->flags&PF_OVERFLOW) goto free_points; if (!(p1->flags&PF_PROJECTED)) g3_project_vertex(p1); if (p1->flags&PF_OVERFLOW) goto free_points; //gr_line(fl2i(p0->sx),fl2i(p0->sy),fl2i(p1->sx),fl2i(p1->sy),false); // gr_line_float(p0->sx,p0->sy,p1->sx,p1->sy); gr_aaline( p0, p1 ); ret = 1; //frees temp points free_points: if (p0->flags & PF_TEMP_POINT) free_temp_point(p0); if (p1->flags & PF_TEMP_POINT) free_temp_point(p1); return ret; } //draws a line. takes two points. returns true if drew int g3_draw_line(vertex *p0,vertex *p1) { #ifdef FRED_OGL_COMMENT_OUT_FOR_NOW if(Fred_running && !Cmdline_nohtl) { gr_aaline( p0, p1 ); return 0; } #endif ubyte codes_or; Assert( G3_count == 1 ); if (p0->codes & p1->codes) return 0; codes_or = (unsigned char)(p0->codes | p1->codes); if (codes_or & CC_BEHIND) return must_clip_line(p0,p1,codes_or,0); if (!(p0->flags&PF_PROJECTED)) g3_project_vertex(p0); if (p0->flags&PF_OVERFLOW) // return 1; return must_clip_line(p0,p1,codes_or,0); if (!(p1->flags&PF_PROJECTED)) g3_project_vertex(p1); if (p1->flags&PF_OVERFLOW) // return 1; return must_clip_line(p0,p1,codes_or,0); // gr_line(fl2i(p0->sx),fl2i(p0->sy),fl2i(p1->sx),fl2i(p1->sy),false); // gr_line_float(p0->sx,p0->sy,p1->sx,p1->sy); gr_aaline( p0, p1 ); return 0; } //returns true if a plane is facing the viewer. takes the unrotated surface //normal of the plane, and a point on it. The normal need not be normalized int g3_check_normal_facing(vec3d *v,vec3d *norm) { vec3d tempv; Assert( G3_count == 1 ); vm_vec_sub(&tempv,&View_position,v); return (vm_vec_dot(&tempv,norm) > 0.0f); } int do_facing_check(vec3d *norm,vertex **vertlist,vec3d *p) { Assert( G3_count == 1 ); if (norm) { //have normal Assert(norm->xyz.x || norm->xyz.y || norm->xyz.z); return g3_check_normal_facing(p,norm); } else { //normal not specified, so must compute vec3d tempv; //get three points (rotated) and compute normal vm_vec_perp(&tempv,(vec3d *)&vertlist[0]->x,(vec3d *)&vertlist[1]->x,(vec3d *)&vertlist[2]->x); return (vm_vec_dot(&tempv,(vec3d *)&vertlist[1]->x ) < 0.0); } } //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 int g3_draw_poly_if_facing(int nv,vertex **pointlist,uint tmap_flags,vec3d *norm,vec3d *pnt) { Assert( G3_count == 1 ); if (do_facing_check(norm,pointlist,pnt)) return g3_draw_poly(nv,pointlist,tmap_flags); else return 255; } //draw a polygon. //Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture. //returns 1 if off screen, 0 if drew int g3_draw_poly(int nv,vertex **pointlist,uint tmap_flags) { int i; vertex **bufptr; ccodes cc; Assert( G3_count == 1 ); if(!Cmdline_nohtl && (tmap_flags & TMAP_HTL_3D_UNLIT)) { gr_tmapper( nv, pointlist, tmap_flags ); return 0; } //don't clip in HT&L mode, the card does it for us if(!Cmdline_nohtl && (tmap_flags & TMAP_FLAG_TRISTRIP)) { gr_tmapper( nv, pointlist, tmap_flags ); return 0; } if(Cmdline_nohtl && (tmap_flags & TMAP_FLAG_TRISTRIP)){ bool starting = true; int offset = 0; for (i=0;iflags&PF_PROJECTED))g3_project_vertex(pointlist[i]); if (pointlist[i]->flags&PF_OVERFLOW){ if(starting) offset++; nv--; }else starting = false; if(nv<3)return 1; } if(nv<3)return 1; pointlist += offset; gr_tmapper( nv, pointlist, tmap_flags ); return 0; } g3_allocate_vbufs(nv); cc.cc_or = 0; cc.cc_and = 0xff; bufptr = Vbuf0; /* if(tmap_flags & TMAP_HTL_3D_UNLIT && !Cmdline_nohtl) { gr_tmapper( nv, pointlist, tmap_flags ); return 0; } */ for (i=0;icodes; cc.cc_or |= p->codes; } if (cc.cc_and) return 1; //all points off screen if (cc.cc_or) { Assert( G3_count == 1 ); bufptr = clip_polygon(Vbuf0,Vbuf1,&nv,&cc,tmap_flags); if (nv && !(cc.cc_or & CC_BEHIND) && !cc.cc_and) { for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { //Int3(); //should not overflow after clip //printf( "overflow in must_clip_tmap_face\n" ); goto free_points; } } gr_tmapper( nv, bufptr, tmap_flags ); } free_points: ; for (i=0;iflags & PF_TEMP_POINT) free_temp_point(bufptr[i]); } else { //now make list of 2d coords (& check for overflow) for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { //Int3(); //should not overflow after clip //printf( "3d: Point overflowed, but flags say OK!\n" ); return 255; } } gr_tmapper( nv, bufptr, tmap_flags ); } return 0; //say it drew } // Draw a polygon. Same as g3_draw_poly, but it bashes sw to a constant value // for all vertexes. Needs to be done after clipping to get them all. //Set TMAP_FLAG_TEXTURED in the tmap_flags to texture map it with current texture. //returns 1 if off screen, 0 if drew int g3_draw_poly_constant_sw(int nv,vertex **pointlist,uint tmap_flags, float constant_sw) { int i; vertex **bufptr; ccodes cc; Assert( G3_count == 1 ); if(!Cmdline_nohtl && (tmap_flags & TMAP_HTL_3D_UNLIT)) { gr_tmapper( nv, pointlist, tmap_flags ); return 0; } if(tmap_flags & TMAP_FLAG_TRISTRIP || tmap_flags & TMAP_FLAG_TRILIST){ for (i=0;iflags&PF_PROJECTED))g3_project_vertex(pointlist[i]); } gr_tmapper( nv, pointlist, tmap_flags ); return 0; } g3_allocate_vbufs(nv); cc.cc_or = 0; cc.cc_and = 0xff; bufptr = Vbuf0; for (i=0;icodes; cc.cc_or |= p->codes; } if (cc.cc_and) return 1; //all points off screen if (cc.cc_or) { Assert( G3_count == 1 ); bufptr = clip_polygon(Vbuf0, Vbuf1, &nv, &cc, tmap_flags); if (nv && !(cc.cc_or & CC_BEHIND) && !cc.cc_and) { for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { //Int3(); //should not overflow after clip //printf( "overflow in must_clip_tmap_face\n" ); goto free_points; } p->sw = constant_sw; } gr_tmapper( nv, bufptr, tmap_flags ); // draw lines connecting the faces /* gr_set_color_fast(&Color_bright_green); for(i=0; iflags & PF_TEMP_POINT){ free_temp_point(bufptr[i]); } } } else { //now make list of 2d coords (& check for overflow) for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { //Int3(); //should not overflow after clip //printf( "3d: Point overflowed, but flags say OK!\n" ); return 255; } p->sw = constant_sw; } gr_tmapper( nv, bufptr, tmap_flags ); // draw lines connecting the faces /* gr_set_color_fast(&Color_bright_green); for(i=0; icodes & CC_BEHIND)) { if (! (pnt->flags & PF_PROJECTED)) g3_project_vertex(pnt); if (! (pnt->codes & PF_OVERFLOW)) { float r2,t; r2 = rad*Matrix_scale.xyz.x; t=r2*Canv_w2/pnt->z; gr_circle(fl2i(pnt->sx),fl2i(pnt->sy),fl2i(t*2.0f),false); } } return 0; } int g3_draw_sphere_ez(vec3d *pnt,float rad) { vertex pt; ubyte flags; Assert( G3_count == 1 ); flags = g3_rotate_vertex(&pt,pnt); if (flags == 0) { g3_project_vertex(&pt); if (!(pt.flags & PF_OVERFLOW)) { g3_draw_sphere( &pt, rad ); } } return 0; } //ID3DXSprite // creates a quad centered around the given point, pointed at the camera /* 0----1 |\ | | \ | 3----2 1.41421356 */ /* int g3_draw_bitmap_3d(vertex *pnt,int orient, float rad,uint tmap_flags, float depth) { //return 0; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and hieght rad vec3d PNT; vm_vert2vec(pnt, &PNT); vec3d p[4]; vertex P[4]; //unused variables that were there for some reason // matrix m; // vm_set_identity(&m); vertex *ptlist[4] = { &P[3], &P[2], &P[1], &P[0] }; float aspect = gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height;//seems that we have to corect for the aspect ratio p[0].xyz.x = rad * aspect; p[0].xyz.y = rad; p[0].xyz.z = -depth; p[1].xyz.x = -rad * aspect; p[1].xyz.y = rad; p[1].xyz.z = -depth; p[2].xyz.x = -rad * aspect; p[2].xyz.y = -rad; p[2].xyz.z = -depth; p[3].xyz.x = rad * aspect; p[3].xyz.y = -rad; p[3].xyz.z = -depth; for(int i = 0; i<4; i++){ vec3d t = p[i]; vm_vec_unrotate(&p[i],&t,&View_matrix);//point it at the eye vm_vec_add2(&p[i],&PNT);//move it } //move all the data from the vecs into the verts g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); g3_transfer_vertex(&P[3], &p[0]); //set up the UV coords P[0].u = 0.0f; P[0].v = 0.0f; P[1].u = 1.0f; P[1].v = 0.0f; P[2].u = 1.0f; P[2].v = 1.0f; P[3].u = 0.0f; P[3].v = 1.0f; gr_set_cull(0); g3_draw_poly(4,ptlist,tmap_flags); gr_set_cull(1); return 0; } */ //alternate method int g3_draw_bitmap_3d(vertex *pnt, int orient, float rad, uint tmap_flags, float depth) { //return 0; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and hieght rad // rad*=3.0f; vec3d PNT; vm_vert2vec(pnt, &PNT); vec3d p[4]; vertex P[4]; vec3d fvec, rvec, uvec; vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize(&fvec); uvec = View_matrix.vec.uvec; vm_vec_crossprod(&rvec, &fvec, &uvec); vm_vec_normalize(&rvec); vm_vec_crossprod(&uvec, &fvec, &rvec); vertex *ptlist[4] = { &P[3], &P[2], &P[1], &P[0] }; // float aspect = gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height;//seems that we have to corect for the aspect ratio vm_vec_scale_add(&PNT, &PNT, &fvec, depth); vm_vec_scale_add(&p[0], &PNT, &rvec, rad); vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); // p[0].xyz.x = rad * aspect; p[0].xyz.y = rad; p[0].xyz.z = -depth; // p[1].xyz.x = -rad * aspect; p[1].xyz.y = rad; p[1].xyz.z = -depth; // p[2].xyz.x = -rad * aspect; p[2].xyz.y = -rad; p[2].xyz.z = -depth; // p[3].xyz.x = rad * aspect; p[3].xyz.y = -rad; p[3].xyz.z = -depth; // for(int i = 0; i<4; i++){ // vec3d t = p[i]; // vm_vec_unrotate(&p[i],&t,&View_matrix);//point it at the eye // vm_vec_add2(&p[i],&PNT);//move it // } //move all the data from the vecs into the verts g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); g3_transfer_vertex(&P[3], &p[0]); // set up the UV coords if ( orient & 1 ) { P[0].u = 1.0f; P[1].u = 0.0f; P[2].u = 0.0f; P[3].u = 1.0f; } else { P[0].u = 0.0f; P[1].u = 1.0f; P[2].u = 1.0f; P[3].u = 0.0f; } if ( orient & 2 ) { P[0].v = 1.0f; P[1].v = 1.0f; P[2].v = 0.0f; P[3].v = 0.0f; } else { P[0].v = 0.0f; P[1].v = 0.0f; P[2].v = 1.0f; P[3].v = 1.0f; } // P[0].u = 0.0f; P[0].v = 0.0f; // P[1].u = 1.0f; P[1].v = 0.0f; // P[2].u = 1.0f; P[2].v = 1.0f; // P[3].u = 0.0f; P[3].v = 1.0f; gr_set_cull(0); g3_draw_poly(4,ptlist,tmap_flags); gr_set_cull(1); return 0; } int g3_draw_bitmap_3d_v(vertex *pnt, int orient, float rad, uint tmap_flags, float depth, float c) { //return 0; // rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and hieght rad vec3d PNT; vm_vert2vec(pnt, &PNT); vec3d p[4]; vertex P[4]; int i; //unused variables that were there for some reason // matrix m; // vm_set_identity(&m); vertex *ptlist[4] = { &P[3], &P[2], &P[1], &P[0] }; float aspect = gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height;//seems that we have to corect for the aspect ratio p[0].xyz.x = rad * aspect; p[0].xyz.y = rad; p[0].xyz.z = -depth; p[1].xyz.x = -rad * aspect; p[1].xyz.y = rad; p[1].xyz.z = -depth; p[2].xyz.x = -rad * aspect; p[2].xyz.y = -rad; p[2].xyz.z = -depth; p[3].xyz.x = rad * aspect; p[3].xyz.y = -rad; p[3].xyz.z = -depth; for(i = 0; i<4; i++){ vec3d t = p[i]; vm_vec_unrotate(&p[i],&t,&View_matrix);//point it at the eye vm_vec_add2(&p[i],&PNT);//move it } //move all the data from the vecs into the verts g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); g3_transfer_vertex(&P[3], &p[0]); for( i = 0; i<4; i++){ P[i].r = (ubyte)(255.0f * c); P[i].g = (ubyte)(255.0f * c); P[i].b = (ubyte)(255.0f * c); } //set up the UV coords P[0].u = 0.0f; P[0].v = 0.0f; P[1].u = 1.0f; P[1].v = 0.0f; P[2].u = 1.0f; P[2].v = 1.0f; P[3].u = 0.0f; P[3].v = 1.0f; gr_set_cull(0); g3_draw_poly(4,ptlist,tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD); gr_set_cull(1); return 0; } int g3_draw_bitmap_3d_volume(vertex *pnt, int orient, float rad, uint tmap_flags, float depth, int resolution) { float s = 1.0f; float res = float(resolution); // float total = 0.0f; for(int i = 0; i bh ) { height = rad*2.0f; width = height*i2fl(bw)/i2fl(bh); } else { width = height = rad*2.0f; } } else { width = height = rad*2.0f; } Assert( G3_count == 1 ); if ( pnt->codes & (CC_BEHIND|CC_OFF_USER) ) return 1; if (!(pnt->flags&PF_PROJECTED)) g3_project_vertex(pnt); if (pnt->flags & PF_OVERFLOW) return 1; t = (width*Canv_w2)/pnt->z; w = t*Matrix_scale.xyz.x; t = (height*Canv_h2)/pnt->z; h = t*Matrix_scale.xyz.y; float z,sw; z = pnt->z - rad/2.0f; if ( z <= 0.0f ) { z = 0.0f; sw = 0.0f; } else { sw = 1.0f / z; } va.sx = pnt->sx - w/2.0f; va.sy = pnt->sy - h/2.0f; va.sw = sw; va.z = z; vb.sx = va.sx + w; vb.sy = va.sy + h; vb.sw = sw; vb.z = z; if ( orient & 1 ) { va.u = 1.0f; vb.u = 0.0f; } else { va.u = 0.0f; vb.u = 1.0f; } if ( orient & 2 ) { va.v = 1.0f; vb.v = 0.0f; } else { va.v = 0.0f; vb.v = 1.0f; } gr_scaler(&va, &vb); return 0; } // get bitmap dims onscreen as if g3_draw_bitmap() had been called int g3_get_bitmap_dims(int bitmap, vertex *pnt, float rad, int *x, int *y, int *w, int *h, int *size) { float t; float width, height; int bw, bh; bm_get_info( bitmap, &bw, &bh, NULL ); if ( bw < bh ) { width = rad*2.0f; height = width*i2fl(bh)/i2fl(bw); } else if ( bw > bh ) { height = rad*2.0f; width = height*i2fl(bw)/i2fl(bh); } else { width = height = rad*2.0f; } Assert( G3_count == 1 ); if ( pnt->codes & (CC_BEHIND|CC_OFF_USER) ) { return 1; } if (!(pnt->flags&PF_PROJECTED)){ g3_project_vertex(pnt); } if (pnt->flags & PF_OVERFLOW){ return 1; } t = (width*Canv_w2)/pnt->z; *w = (int)(t*Matrix_scale.xyz.x); t = (height*Canv_h2)/pnt->z; *h = (int)(t*Matrix_scale.xyz.y); *x = (int)(pnt->sx - *w/2.0f); *y = (int)(pnt->sy - *h/2.0f); *size = MAX(bw, bh); return 0; } /* int g3_draw_rotated_bitmap_3d(vertex *pnt,float angle, float rad,uint tmap_flags, float depth){ // return 0; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and hieght rad angle+=Physics_viewer_bank; if ( angle < 0.0f ) angle += PI2; else if ( angle > PI2 ) angle -= PI2; float sa = (float)sin(angle); float ca = (float)cos(angle); vec3d PNT; vm_vert2vec(pnt, &PNT); vec3d p[4]; vertex P[4]; matrix m; vm_set_identity(&m); vertex *ptlist[4] = { &P[3], &P[2], &P[1], &P[0] }; float aspect = gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height;//seems that we have to corect for the aspect ratio p[0].xyz.x = (-rad*ca + rad*sa) * aspect; p[0].xyz.y = (-rad*sa - rad*ca); p[0].xyz.z = -depth; p[1].xyz.x = (rad*ca + rad*sa) * aspect; p[1].xyz.y = (rad*sa - rad*ca); p[1].xyz.z = -depth; p[2].xyz.x = (rad*ca - rad*sa) * aspect; p[2].xyz.y = (rad*sa + rad*ca); p[2].xyz.z = -depth; p[3].xyz.x = (-rad*ca - rad*sa) * aspect; p[3].xyz.y = (-rad*sa + rad*ca); p[3].xyz.z = -depth; for(int i = 0; i<4; i++){ vec3d t = p[i]; vm_vec_unrotate(&p[i],&t,&View_matrix);//point it at the eye vm_vec_add2(&p[i],&PNT);//move it } //move all the data from the vecs into the verts g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); g3_transfer_vertex(&P[3], &p[0]); //set up the UV coords P[0].u = 0.0f; P[0].v = 0.0f; P[1].u = 1.0f; P[1].v = 0.0f; P[2].u = 1.0f; P[2].v = 1.0f; P[3].u = 0.0f; P[3].v = 1.0f; gr_set_cull(0); g3_draw_poly(4,ptlist,tmap_flags); gr_set_cull(1); return 0; } */ //alternate method int g3_draw_rotated_bitmap_3d(vertex *pnt,float angle, float rad,uint tmap_flags, float depth){ //return 0; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and hieght rad angle+=Physics_viewer_bank; if ( angle < 0.0f ) angle += PI2; else if ( angle > PI2 ) angle -= PI2; vec3d PNT; vm_vert2vec(pnt, &PNT); vec3d p[4]; vertex P[4]; vec3d fvec, rvec, uvec; vm_vec_sub(&fvec, &View_position, &PNT); // VECMAT-ERROR: NULL VEC3D (PNT == View_position, multiplayer respawn or death sequence) vm_vec_normalize_safe(&fvec); vm_rot_point_around_line(&uvec, &View_matrix.vec.uvec, angle, &vmd_zero_vector, &fvec); // uvec = View_matrix.vec.uvec; vm_vec_crossprod(&rvec, &fvec, &uvec); vm_vec_normalize(&rvec); vm_vec_crossprod(&uvec, &fvec, &rvec); vertex *ptlist[4] = { &P[3], &P[2], &P[1], &P[0] }; // float aspect = gr_screen.aspect*(float)gr_screen.clip_width/(float)gr_screen.clip_height;//seems that we have to corect for the aspect ratio vm_vec_scale_add(&PNT, &PNT, &fvec, depth); vm_vec_scale_add(&p[0], &PNT, &rvec, rad); vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); //move all the data from the vecs into the verts g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); g3_transfer_vertex(&P[3], &p[0]); //set up the UV coords P[0].u = 0.0f; P[0].v = 0.0f; P[1].u = 1.0f; P[1].v = 0.0f; P[2].u = 1.0f; P[2].v = 1.0f; P[3].u = 0.0f; P[3].v = 1.0f; gr_set_cull(0); g3_draw_poly(4,ptlist,tmap_flags); gr_set_cull(1); return 0; } //draws a bitmap with the specified 3d width & height //returns 1 if off screen, 0 if drew int g3_draw_rotated_bitmap(vertex *pnt,float angle, float rad,uint tmap_flags, float depth) { if(!Cmdline_nohtl && (tmap_flags & TMAP_HTL_3D_UNLIT)) { return g3_draw_rotated_bitmap_3d(pnt, angle, rad, tmap_flags, depth); } vertex v[4]; vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] }; float sa, ca; int i; memset(v,0,sizeof(vertex)*4); /* if ( !Detail.alpha_effects ) { int ang; if ( angle < PI_2 ) { ang = 0; } else if ( angle < PI ) { ang = 1; } else if ( angle < PI+PI_2 ) { ang = 2; } else { ang = 3; } return g3_draw_bitmap( pnt, ang, rad, tmap_flags ); } */ Assert( G3_count == 1 ); angle+=Physics_viewer_bank; if ( angle < 0.0f ) angle += PI2; else if ( angle > PI2 ) angle -= PI2; // angle = 0.0f; sa = (float)sin(angle); ca = (float)cos(angle); float width, height; if ( tmap_flags & TMAP_FLAG_TEXTURED ) { int bw, bh; bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL ); if ( bw < bh ) { width = rad; height = width*i2fl(bh)/i2fl(bw); } else if ( bw > bh ) { height = rad; width = height*i2fl(bw)/i2fl(bh); } else { width = height = rad; } } else { width = height = rad; } v[0].x = (-width*ca + height*sa)*Matrix_scale.xyz.x + pnt->x; v[0].y = (-width*sa - height*ca)*Matrix_scale.xyz.y + pnt->y; v[0].z = pnt->z; v[0].sw = 0.0f; v[0].u = 0.0f; v[0].v = 1.0f; v[1].x = (width*ca + height*sa)*Matrix_scale.xyz.x + pnt->x; v[1].y = (width*sa - height*ca)*Matrix_scale.xyz.y + pnt->y; v[1].z = pnt->z; v[1].sw = 0.0f; v[1].u = 1.0f; v[1].v = 1.0f; v[2].x = (width*ca - height*sa)*Matrix_scale.xyz.x + pnt->x; v[2].y = (width*sa + height*ca)*Matrix_scale.xyz.y + pnt->y; v[2].z = pnt->z; v[2].sw = 0.0f; v[2].u = 1.0f; v[2].v = 0.0f; v[3].x = (-width*ca - height*sa)*Matrix_scale.xyz.x + pnt->x; v[3].y = (-width*sa + height*ca)*Matrix_scale.xyz.y + pnt->y; v[3].z = pnt->z; v[3].sw = 0.0f; v[3].u = 0.0f; v[3].v = 0.0f; ubyte codes_and=0xff; float sw,z; z = pnt->z - rad / 4.0f; if ( z < 0.0f ) z = 0.0f; sw = 1.0f / z; for (i=0; i<4; i++ ) { //now code the four points codes_and &= g3_code_vertex(&v[i]); v[i].flags = 0; // mark as not yet projected //g3_project_vertex(&v[i]); } if (codes_and) return 1; //1 means off screen // clip and draw it g3_draw_poly_constant_sw(4, vertlist, tmap_flags, sw ); return 0; } #define TRIANGLE_AREA(_p, _q, _r) do { vec3d a, b, cross; a.xyz.x = _q->x - _p->x; a.xyz.y = _q->y - _p->y; a.xyz.z = 0.0f; b.xyz.x = _r->x - _p->x; b.xyz.y = _r->y - _p->y; b.xyz.z = 0.0f; vm_vec_crossprod(&cross, &a, &b); total_area += vm_vec_mag(&cross) * 0.5f; } while(0); float g3_get_poly_area(int nv, vertex **pointlist) { int idx; float total_area = 0.0f; // each triangle for(idx=1; idx TMAP_MAX_VERTS ) { // Int3(); // return 0.0f; // } g3_allocate_vbufs(nv); cc.cc_or = 0; cc.cc_and = 0xff; bufptr = Vbuf0; for (i=0;icodes; cc.cc_or |= p->codes; } if (cc.cc_and){ return 0.0f; //all points off screen } if (cc.cc_or) { Assert( G3_count == 1 ); bufptr = clip_polygon(Vbuf0, Vbuf1, &nv, &cc, tmap_flags); if (nv && !(cc.cc_or & CC_BEHIND) && !cc.cc_and) { for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { //Int3(); //should not overflow after clip //printf( "overflow in must_clip_tmap_face\n" ); goto free_points; } p->sw = constant_sw; } // check area p_area = g3_get_poly_area(nv, bufptr); if(p_area > area){ return 0.0f; } gr_tmapper( nv, bufptr, tmap_flags ); } free_points: ; for (i=0;iflags & PF_TEMP_POINT){ free_temp_point(bufptr[i]); } } } else { //now make list of 2d coords (& check for overflow) for (i=0;iflags&PF_PROJECTED)) g3_project_vertex(p); if (p->flags&PF_OVERFLOW) { return 0.0f; } p->sw = constant_sw; } // check area p_area = g3_get_poly_area(nv, bufptr); if(p_area > area){ return 0.0f; } gr_tmapper( nv, bufptr, tmap_flags ); } // how much area we drew return p_area; } //draws a bitmap with the specified 3d width & height //returns 1 if off screen, 0 if drew float g3_draw_rotated_bitmap_area(vertex *pnt,float angle, float rad,uint tmap_flags, float area) { vertex v[4]; vertex *vertlist[4] = { &v[3], &v[2], &v[1], &v[0] }; float sa, ca; int i; memset(v,0,sizeof(vertex)*4); Assert( G3_count == 1 ); angle+=Physics_viewer_bank; if ( angle < 0.0f ){ angle += PI2; } else if ( angle > PI2 ) { angle -= PI2; } sa = (float)sin(angle); ca = (float)cos(angle); float width, height; if ( tmap_flags & TMAP_FLAG_TEXTURED ) { int bw, bh; bm_get_info( gr_screen.current_bitmap, &bw, &bh, NULL ); if ( bw < bh ) { width = rad; height = width*i2fl(bh)/i2fl(bw); } else if ( bw > bh ) { height = rad; width = height*i2fl(bw)/i2fl(bh); } else { width = height = rad; } } else { width = height = rad; } v[0].x = (-width*ca + height*sa)*Matrix_scale.xyz.x + pnt->x; v[0].y = (-width*sa - height*ca)*Matrix_scale.xyz.y + pnt->y; v[0].z = pnt->z; v[0].sw = 0.0f; v[0].u = 0.0f; v[0].v = 1.0f; v[1].x = (width*ca + height*sa)*Matrix_scale.xyz.x + pnt->x; v[1].y = (width*sa - height*ca)*Matrix_scale.xyz.y + pnt->y; v[1].z = pnt->z; v[1].sw = 0.0f; v[1].u = 1.0f; v[1].v = 1.0f; v[2].x = (width*ca - height*sa)*Matrix_scale.xyz.x + pnt->x; v[2].y = (width*sa + height*ca)*Matrix_scale.xyz.y + pnt->y; v[2].z = pnt->z; v[2].sw = 0.0f; v[2].u = 1.0f; v[2].v = 0.0f; v[3].x = (-width*ca - height*sa)*Matrix_scale.xyz.x + pnt->x; v[3].y = (-width*sa + height*ca)*Matrix_scale.xyz.y + pnt->y; v[3].z = pnt->z; v[3].sw = 0.0f; v[3].u = 0.0f; v[3].v = 0.0f; ubyte codes_and=0xff; float sw,z; z = pnt->z - rad / 4.0f; if ( z < 0.0f ) z = 0.0f; sw = 1.0f / z; for (i=0; i<4; i++ ) { //now code the four points codes_and &= g3_code_vertex(&v[i]); v[i].flags = 0; // mark as not yet projected //g3_project_vertex(&v[i]); } if (codes_and){ return 0.0f; } // clip and draw it return g3_draw_poly_constant_sw_area(4, vertlist, tmap_flags, sw, area ); } #include "graphics/2d.h" typedef struct horz_pt { float x, y; int edge; } horz_pt; //draws a horizon. takes eax=sky_color, edx=ground_color void g3_draw_horizon_line() { //int sky_color,int ground_color int s1, s2; int cpnt; horz_pt horz_pts[4]; // 0 = left, 1 = right // int top_color, bot_color; // int color_swap; //flag for if we swapped // int sky_ground_flag; //0=both, 1=all sky, -1=all gnd vec3d horizon_vec; float up_right, down_right,down_left,up_left; // color_swap = 0; //assume no swap // sky_ground_flag = 0; //assume both // if ( View_matrix.uvec.xyz.y < 0.0f ) // color_swap = 1; // else if ( View_matrix.uvec.xyz.y == 0.0f ) { // if ( View_matrix.uvec.xyz.x > 0.0f ) // color_swap = 1; // } // if (color_swap) { // top_color = ground_color; // bot_color = sky_color; // } else { // top_color = sky_color; // bot_color = ground_color; // } Assert( G3_count == 1 ); //compute horizon_vector horizon_vec.xyz.x = Unscaled_matrix.vec.rvec.xyz.y*Matrix_scale.xyz.y*Matrix_scale.xyz.z; horizon_vec.xyz.y = Unscaled_matrix.vec.uvec.xyz.y*Matrix_scale.xyz.x*Matrix_scale.xyz.z; horizon_vec.xyz.z = Unscaled_matrix.vec.fvec.xyz.y*Matrix_scale.xyz.x*Matrix_scale.xyz.y; // now compute values & flag for 4 corners. up_right = horizon_vec.xyz.x + horizon_vec.xyz.y + horizon_vec.xyz.z; down_right = horizon_vec.xyz.x - horizon_vec.xyz.y + horizon_vec.xyz.z; down_left = -horizon_vec.xyz.x - horizon_vec.xyz.y + horizon_vec.xyz.z; up_left = -horizon_vec.xyz.x + horizon_vec.xyz.y + horizon_vec.xyz.z; //check flags for all sky or all ground. if ( (up_right<0.0f)&&(down_right<0.0f)&&(down_left<0.0f)&&(up_left<0.0f) ) { // mprintf(( "All ground.\n" )); return; } if ( (up_right>0.0f)&&(down_right>0.0f)&&(down_left>0.0f)&&(up_left>0.0f) ) { // mprintf(( "All sky.\n" )); return; } //mprintf(( "Horizon vec = %.4f, %.4f, %.4f\n", horizon_vec.xyz.x, horizon_vec.xyz.y, horizon_vec.xyz.z )); //mprintf(( "%.4f, %.4f, %.4f, %.4f\n", up_right, down_right, down_left, up_left )); // mprintf(( "u: %.4f %.4f %.4f c: %.4f %.4f %.4f %.4f\n",Unscaled_matrix.vec.uvec.xyz.y,Unscaled_matrix.vec.uvec.xyz.z,Unscaled_matrix.vec.uvec.xyz.x,up_left,up_right,down_right,down_left )); // check for intesection with each of four edges & compute horizon line cpnt = 0; // check intersection with left edge s1 = up_left > 0.0f; s2 = down_left > 0.0f; if ( s1 != s2 ) { horz_pts[cpnt].x = 0.0f; horz_pts[cpnt].y = fl_abs(up_left * Canv_h2 / horizon_vec.xyz.y); horz_pts[cpnt].edge = 0; cpnt++; } // check intersection with top edge s1 = up_left > 0.0f; s2 = up_right > 0.0f; if ( s1 != s2 ) { horz_pts[cpnt].x = fl_abs(up_left * Canv_w2 / horizon_vec.xyz.x); horz_pts[cpnt].y = 0.0f; horz_pts[cpnt].edge = 1; cpnt++; } // check intersection with right edge s1 = up_right > 0.0f; s2 = down_right > 0.0f; if ( s1 != s2 ) { horz_pts[cpnt].x = i2fl(Canvas_width)-1; horz_pts[cpnt].y = fl_abs(up_right * Canv_h2 / horizon_vec.xyz.y); horz_pts[cpnt].edge = 2; cpnt++; } //check intersection with bottom edge s1 = down_right > 0.0f; s2 = down_left > 0.0f; if ( s1 != s2 ) { horz_pts[cpnt].x = fl_abs(down_left * Canv_w2 / horizon_vec.xyz.x); horz_pts[cpnt].y = i2fl(Canvas_height)-1; horz_pts[cpnt].edge = 3; cpnt++; } if ( cpnt != 2 ) { mprintf(( "HORZ: Wrong number of points (%d)\n", cpnt )); return; } //make sure first edge is left if ( horz_pts[0].x > horz_pts[1].x ) { horz_pt tmp; tmp = horz_pts[0]; horz_pts[0] = horz_pts[1]; horz_pts[1] = tmp; } // draw from left to right. gr_line( fl2i(horz_pts[0].x),fl2i(horz_pts[0].y),fl2i(horz_pts[1].x),fl2i(horz_pts[1].y), false ); } /* horizon_poly dw 5 dup (?,?) ;max of 5 points ;for g3_compute_horz_vecs xfrac fix ? yfrac fix ? vec_ptr dd ? corner_num dd ? ;for compute corner vec m13 fix ? ;m1-m3 m46 fix ? m79 fix ? m56 fix ? m23 fix ? m89 fix ? _DATA ends _TEXT segment dword public USE32 'CODE' extn gr_setcolor_,gr_clear_canvas_ extn gr_upoly_tmap_ ;draw a polygon (one half of horizon) from the horizon line draw_horz_poly: lea ebx,horizon_poly ;copy horizon line as first points in poly mov eax,[edi] mov [ebx],eax mov eax,4[edi] mov 4[ebx],eax mov eax,[esi] mov 8[ebx],eax mov eax,4[esi] mov 12[ebx],eax ;add corners to polygon mov eax,8[esi] ;edge number of start edge mov ecx,8[edi] ;edge number of end point sub ecx,eax ;number of edges jns edgenum_ok add ecx,4 edgenum_ok: mov edx,ecx ;save count sal eax,3 ;edge * 8 lea esi,corners[eax] ;first corner lea edi,16[ebx] ;rest of poly corner_loop: movsd movsd ;copy a corner cmp esi,offset corners+8*4 ;end of list? jne no_wrap lea esi,corners no_wrap: loop corner_loop ;now draw the polygon mov eax,edx ;get corner count add eax,2 ;..plus horz line end points lea edx,horizon_poly ;get the points ;; call gr_poly_ ;draw it! call gr_upoly_tmap_ ret ;return information on the polygon that is the sky. ;takes ebx=ptr to x,y pairs, ecx=ptr to vecs for each point ;returns eax=number of points ;IMPORTANT: g3_draw_horizon() must be called before this routine. g3_compute_sky_polygon: test sky_ground_flag,-1 ;what was drawn js was_all_ground jg was_all_sky pushm ebx,ecx,edx,esi,edi lea esi,left_point lea edi,right_point test color_swap,-1 jz no_swap_ends xchg esi,edi ;sky isn't top no_swap_ends: ;copy horizon line as first points in poly mov eax,[edi] ;copy end point mov [ebx],eax mov eax,4[edi] mov 4[ebx],eax mov eax,[esi] ;copy start point mov 8[ebx],eax mov eax,4[esi] mov 12[ebx],eax pushm ebx,ecx push edi ;save end point push esi ;save start point mov esi,edi ;end point is first point mov edi,ecx ;dest buffer call compute_horz_end_vec pop esi ;get back start point add edi,12 ;2nd vec call compute_horz_end_vec pop edi ;get back end point popm ebx,ecx add ebx,16 ;past two x,y pairs add ecx,24 ;past two vectors mov vec_ptr,ecx ;add corners to polygon mov eax,8[esi] ;edge number of start edge mov corner_num,eax mov ecx,8[edi] ;edge number of end point sub ecx,eax ;number of edges jns edgenum_ok2 add ecx,4 edgenum_ok2: push ecx ;save count sal eax,3 ;edge * 8 lea esi,corners[eax] ;first corner mov edi,ebx ;rest of poly 2d points corner_loop2: movsd movsd ;copy a corner cmp esi,offset corners+8*4 ;end of list? jne no_wrap2 lea esi,corners no_wrap2: pushm ecx,esi,edi mov edi,vec_ptr mov eax,corner_num call compute_corner_vec add vec_ptr,12 inc corner_num popm ecx,esi,edi loop corner_loop2 ;now return with count pop eax ;get corner count add eax,2 ;..plus horz line end points popm ebx,ecx,edx,esi,edi ret ;we drew all ground, so there was no horizon drawn was_all_ground: xor eax,eax ;no points in poly ret ;we drew all sky, so find 4 corners was_all_sky: pushm ebx,ecx,edx,esi,edi push ecx lea esi,corners mov edi,ebx mov ecx,8 rep movsd pop edi mov ecx,4 xor eax,eax ;start corner 0 sky_loop: pushm eax,ecx,edi call compute_corner_vec popm eax,ecx,edi add edi,12 inc eax loop sky_loop mov eax,4 ;4 corners popm ebx,ecx,edx,esi,edi ret ;compute vec3d describing horizon intersection with a point. ;takes esi=2d point, edi=vec. trashes eax,ebx,ecx,edx compute_horz_end_vec: ;compute rotated x/z & y/z ratios mov eax,[esi] ;get x coord sub eax,Canv_w2 fixdiv Canv_w2 mov xfrac,eax ;save mov eax,4[esi] ;get y coord sub eax,Canv_h2 fixdiv Canv_h2 neg eax ;y inversion mov yfrac,eax ;save ;compute fraction unrotated x/z mov eax,xfrac add eax,yfrac mov ecx,eax ;save fixmul View_matrix.m9 sub eax,View_matrix.m7 sub eax,View_matrix.m8 mov ebx,eax ;save numerator mov eax,ecx fixmul View_matrix.m3 mov ecx,eax mov eax,View_matrix.m1 add eax,View_matrix.m2 sub eax,ecx ;now eax/ebx = z/x. do divide in way to give result < 0 pushm eax,ebx abs_eax xchg eax,ebx abs_eax cmp eax,ebx ;which is bigger? popm eax,ebx jl do_xz ;x is bigger, so do as z/x fixdiv ebx ;now eax = z/x ratio. Compute vec3d by normalizing and correcting sign push eax ;save ratio imul eax ;compute z*z inc edx ;+ x*x (x==1) call quad_sqrt mov ecx,eax ;mag in ecx pop eax ;get ratio, x part fixdiv ecx mov [edi].xyz.z,eax mov eax,f1_0 fixdiv ecx mov [edi].xyz.x,eax jmp finish_end ;z is bigger, so do as x/z do_xz: xchg eax,ebx fixdiv ebx ;now eax = x/z ratio. Compute vec3d by normalizing and correcting sign push eax ;save ratio imul eax ;compute x*x inc edx ;+ z*z (z==1) call quad_sqrt mov ecx,eax ;mag in ecx pop eax ;get ratio, x part fixdiv ecx mov [edi].xyz.x,eax mov eax,f1_0 fixdiv ecx mov [edi].xyz.z,eax finish_end: xor eax,eax ;y = 0 mov [edi].xyz.y,eax ;now make sure that this vec3d is in front of you, not behind mov eax,[edi].xyz.x imul View_matrix.m3 mov ebx,eax mov ecx,edx mov eax,[edi].xyz.z imul View_matrix.m9 add eax,ebx adc edx,ecx jns vec_ok ;has positive z, ok ;z is neg, flip vector neg [edi].xyz.x neg [edi].xyz.z vec_ok: ret MIN_DEN equ 7fffh sub2 macro dest,src mov eax,src sal eax,1 sub dest,eax endm ;compute vec3d decribing a corner of the screen. ;takes edi=vector, eax=corner num compute_corner_vec: cmp eax,4 jl num_ok sub eax,4 num_ok: ;compute all deltas mov ebx,View_matrix.m1 mov ecx,View_matrix.m4 mov edx,View_matrix.m7 or eax,eax jz neg_x cmp eax,3 jne no_neg_x neg_x: neg ebx neg ecx neg edx no_neg_x: sub ebx,View_matrix.m3 mov m13,ebx ;m1-m3 sub ecx,View_matrix.m6 mov m46,ecx ;m4-m6 sub edx,View_matrix.m9 mov m79,edx ;m7-m9 mov ebx,View_matrix.m5 mov ecx,View_matrix.m2 mov edx,View_matrix.m8 cmp eax,2 jl no_neg_y neg_y: neg ebx neg ecx neg edx no_neg_y: sub ebx,View_matrix.m6 mov m56,ebx ;m5-m6 sub ecx,View_matrix.m3 mov m23,ecx ;m2-m3 sub edx,View_matrix.m9 mov m89,edx ;m8-m9 ;compute x/z ratio ;compute denomonator mov eax,m46 fixmul m23 mov ebx,eax ;save mov eax,m56 fixmul m13 sub eax,ebx ;eax = denominator ;now we have the denominator. If it is too small, try x/y, z/y or z/x, y/x mov ecx,eax ;save den abs_eax cmp eax,MIN_DEN jl z_too_small z_too_small: ;now do x/z numerator mov eax,m79 fixmul m56 ;* (m5-m6) mov ebx,eax mov eax,m89 fixmul m46 ;* (m4-m6) sub eax,ebx ;now, eax/ecx = x/z ratio fixdiv ecx ;eax = x/z mov [edi].xyz.x,eax ;save x ;now do y/z mov eax,m89 fixmul m13 mov ebx,eax mov eax,m79 fixmul m23 sub eax,ebx ;now eax/ecx = y/z ratio fixdiv ecx mov [edi].xyz.y,eax mov [edi].xyz.z,f1_0 mov esi,edi call vm_vec_normalize ;make sure this vec is pointing in right direction lea edi,View_matrix.vec.fvec call vm_vec_dotprod or eax,eax ;check sign jg vec_sign_ok neg [esi].xyz.x neg [esi].xyz.y neg [esi].xyz.z vec_sign_ok: ret _TEXT ends end */ // Draws a polygon always facing the viewer. // compute the corners of a rod. fills in vertbuf. // Verts has any needs uv's or l's or can be NULL if none needed. int g3_draw_rod(vec3d *p0,float width1,vec3d *p1,float width2, vertex * verts, uint tmap_flags) { vec3d uvec, fvec, rvec, center; vm_vec_sub( &fvec, p0, p1 ); vm_vec_normalize_safe( &fvec ); vm_vec_avg( ¢er, p0, p1 ); vm_vec_sub( &rvec, &Eye_position, ¢er ); vm_vec_normalize( &rvec ); vm_vec_crossprod(&uvec,&fvec,&rvec); //normalize new perpendicular vector vm_vec_normalize(&uvec); //now recompute right vector, in case it wasn't entirely perpendiclar vm_vec_crossprod(&rvec,&uvec,&fvec); // Now have uvec, which is up vector and rvec which is the normal // of the face. int i; vec3d vecs[4]; vertex pts[4]; vertex *ptlist[4] = { &pts[3], &pts[2], &pts[1], &pts[0] }; vm_vec_scale_add( &vecs[0], p0, &uvec, width1/2.0f ); vm_vec_scale_add( &vecs[1], p1, &uvec, width2/2.0f ); vm_vec_scale_add( &vecs[2], p1, &uvec, -width2/2.0f ); vm_vec_scale_add( &vecs[3], p0, &uvec, -width1/2.0f ); for (i=0; i<4; i++ ) { if ( verts ) { pts[i] = verts[i]; } if(Cmdline_nohtl) g3_rotate_vertex( &pts[i], &vecs[i] ); else g3_transfer_vertex( &pts[i], &vecs[i] ); } ptlist[0]->u = 0.0f; ptlist[0]->v = 0.0f; ptlist[0]->r = gr_screen.current_color.red; ptlist[0]->g = gr_screen.current_color.green; ptlist[0]->b = gr_screen.current_color.blue; ptlist[0]->a = gr_screen.current_color.alpha; ptlist[1]->u = 1.0f; ptlist[1]->v = 0.0f; ptlist[1]->r = gr_screen.current_color.red; ptlist[1]->g = gr_screen.current_color.green; ptlist[1]->b = gr_screen.current_color.blue; ptlist[1]->a = gr_screen.current_color.alpha; ptlist[2]->u = 1.0f; ptlist[2]->v = 1.0f; ptlist[2]->r = gr_screen.current_color.red; ptlist[2]->g = gr_screen.current_color.green; ptlist[2]->b = gr_screen.current_color.blue; ptlist[2]->a = gr_screen.current_color.alpha; ptlist[3]->u = 0.0f; ptlist[3]->v = 1.0f; ptlist[3]->r = gr_screen.current_color.red; ptlist[3]->g = gr_screen.current_color.green; ptlist[3]->b = gr_screen.current_color.blue; ptlist[3]->a = gr_screen.current_color.alpha; return g3_draw_poly(4,ptlist,tmap_flags); } // draw a perspective bitmap based on angles and radius vec3d g3_square[4] = { { { { -1.0f, -1.0f, 20.0f } } }, { { { -1.0f, 1.0f, 20.0f } } }, { { { 1.0f, 1.0f, 20.0f } } }, { { { 1.0f, -1.0f, 20.0f } } } }; #define MAX_PERSPECTIVE_DIVISIONS 5 // should never even come close to this limit void stars_project_2d_onto_sphere( vec3d *pnt, float rho, float phi, float theta ) { float a = 3.14159f * phi; float b = 6.28318f * theta; float sin_a = (float)sin(a); // coords pnt->xyz.z = rho * sin_a * (float)cos(b); pnt->xyz.y = rho * sin_a * (float)sin(b); pnt->xyz.x = rho * (float)cos(a); } // draw a perspective bitmap based on angles and radius float p_phi = 10.0f; float p_theta = 10.0f; int g3_draw_perspective_bitmap(angles *a, float scale_x, float scale_y, int div_x, int div_y, uint tmap_flags) { vec3d s_points[MAX_PERSPECTIVE_DIVISIONS+1][MAX_PERSPECTIVE_DIVISIONS+1]; vec3d t_points[MAX_PERSPECTIVE_DIVISIONS+1][MAX_PERSPECTIVE_DIVISIONS+1]; vertex v[4]; vertex *verts[4]; matrix m, m_bank; int idx, s_idx; int saved_zbuffer_mode; float ui, vi; angles bank_first; // cap division values // div_x = div_x > MAX_PERSPECTIVE_DIVISIONS ? MAX_PERSPECTIVE_DIVISIONS : div_x; div_x = 1; div_y = div_y > MAX_PERSPECTIVE_DIVISIONS ? MAX_PERSPECTIVE_DIVISIONS : div_y; // texture increment values ui = 1.0f / (float)div_x; vi = 1.0f / (float)div_y; // adjust for aspect ratio scale_x *= ((float)gr_screen.max_w / (float)gr_screen.max_h) + 0.55f; // fudge factor float s_phi = 0.5f + (((p_phi * scale_x) / 360.0f) / 2.0f); float s_theta = (((p_theta * scale_y) / 360.0f) / 2.0f); float d_phi = -(((p_phi * scale_x) / 360.0f) / (float)(div_x)); float d_theta = -(((p_theta * scale_y) / 360.0f) / (float)(div_y)); // bank matrix bank_first.p = 0.0f; bank_first.b = a->b; bank_first.h = 0.0f; vm_angles_2_matrix(&m_bank, &bank_first); // convert angles to matrix float b_save = a->b; a->b = 0.0f; vm_angles_2_matrix(&m, a); a->b = b_save; // generate the bitmap points for(idx=0; idx<=div_x; idx++){ for(s_idx=0; s_idx<=div_y; s_idx++){ // get world spherical coords stars_project_2d_onto_sphere(&s_points[idx][s_idx], 1000.0f, s_phi + ((float)idx*d_phi), s_theta + ((float)s_idx*d_theta)); // bank the bitmap first vm_vec_rotate(&t_points[idx][s_idx], &s_points[idx][s_idx], &m_bank); // rotate on the sphere vm_vec_rotate(&s_points[idx][s_idx], &t_points[idx][s_idx], &m); } } // turn off zbuffering saved_zbuffer_mode = gr_zbuffer_get(); gr_zbuffer_set(GR_ZBUFF_NONE); // turn off culling gr_set_cull(0); // render all polys for(idx=0; idxbitmap_2d_poly_list_size){ if(bitmap_2d_poly_list)delete[]bitmap_2d_poly_list; if(bitmap_2d_poly_vertlist)delete[]bitmap_2d_poly_vertlist; bitmap_2d_poly_list = new vertex[6* n_bm]; bitmap_2d_poly_vertlist = new vertex*[6*n_bm]; for(int i = 0; i<6*n_bm; i++)bitmap_2d_poly_vertlist[i] = &bitmap_2d_poly_list[i]; memset(bitmap_2d_poly_list,0,sizeof(vertex)*6*n_bm); } g3_start_frame(1); // turn off zbuffering saved_zbuffer_mode = gr_zbuffer_get(); gr_zbuffer_set(GR_ZBUFF_NONE); for(int i = 0; isx = (float)b_list[i].x; V->sy = (float)b_list[i].y; V->sw = 0.0f; V->u = 0.0f; V->v = 0.0f; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b_list[i].x + b_list[i].w); V->sy = (float)b_list[i].y; V->sw = 0.0f; V->u = 1.0f; V->v = 0.0f; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b_list[i].x + b_list[i].w); V->sy = (float)(b_list[i].y + b_list[i].h); V->sw = 0.0f; V->u = 1.0f; V->v = 1.0f; V->flags = PF_PROJECTED; V->codes = 0; //tri two V++; V->sx = (float)b_list[i].x; V->sy = (float)b_list[i].y; V->sw = 0.0f; V->u = 0.0f; V->v = 0.0f; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b_list[i].x + b_list[i].w); V->sy = (float)(b_list[i].y + b_list[i].h); V->sw = 0.0f; V->u = 1.0f; V->v = 1.0f; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)b_list[i].x; V->sy = (float)(b_list[i].y + b_list[i].h); V->sw = 0.0f; V->u = 0.0f; V->v = 1.0f; V->flags = PF_PROJECTED; V->codes = 0; } // no filtering gr_filter_set(0); // set debrief ret = g3_draw_poly_constant_sw(6*n_bm, bitmap_2d_poly_vertlist, TMAP_FLAG_TEXTURED | TMAP_FLAG_TRILIST | additional_tmap_flags, 0.1f); g3_end_frame(); gr_zbuffer_set(saved_zbuffer_mode); // put filtering back on gr_filter_set(1); return ret; } //draws an array of bitmap_rect_list objects //see tmapper.h for explaination of structure bitmap_rect_list int g3_draw_2d_poly_bitmap_rect_list(bitmap_rect_list* b_list, int n_bm, uint additional_tmap_flags) { int ret; int saved_zbuffer_mode; if(n_bm>bitmap_2d_poly_list_size){ if(bitmap_2d_poly_list)delete[]bitmap_2d_poly_list; if(bitmap_2d_poly_vertlist)delete[]bitmap_2d_poly_vertlist; bitmap_2d_poly_list = new vertex[6* n_bm]; bitmap_2d_poly_vertlist = new vertex*[6*n_bm]; for(int i = 0; i<6*n_bm; i++)bitmap_2d_poly_vertlist[i] = &bitmap_2d_poly_list[i]; // memset(bitmap_2d_poly_list,0,sizeof(vertex)*6*n_bm); } g3_start_frame(1); // turn off zbuffering saved_zbuffer_mode = gr_zbuffer_get(); gr_zbuffer_set(GR_ZBUFF_NONE); for(int i = 0; isx = (float)b->x; V->sy = (float)b->y; V->sw = 0.0f; V->u = (float)t->x; V->v = (float)t->y; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b->x + b->w); V->sy = (float)b->y; V->sw = 0.0f; V->u = (float)(t->x + t->w); V->v = (float)t->y; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b->x + b->w); V->sy = (float)(b->y + b->h); V->sw = 0.0f; V->u = (float)(t->x + t->w); V->v = (float)(t->y + t->h); V->flags = PF_PROJECTED; V->codes = 0; //tri two V++; V->sx = (float)b->x; V->sy = (float)b->y; V->sw = 0.0f; V->u = (float)t->x; V->v = (float)t->y; V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)(b->x + b->w); V->sy = (float)(b->y + b->h); V->sw = 0.0f; V->u = (float)(t->x + t->w); V->v = (float)(t->y + t->h); V->flags = PF_PROJECTED; V->codes = 0; V++; V->sx = (float)b->x; V->sy = (float)(b->y + b->h); V->sw = 0.0f; V->u = (float)t->x; V->v = (float)(t->y + t->h); V->flags = PF_PROJECTED; V->codes = 0; } // no filtering gr_filter_set(0); // set debrief ret = g3_draw_poly_constant_sw(6*n_bm, bitmap_2d_poly_vertlist, TMAP_FLAG_TEXTURED | TMAP_FLAG_TRILIST | additional_tmap_flags, 0.1f); g3_end_frame(); gr_zbuffer_set(saved_zbuffer_mode); // put filtering back on gr_filter_set(1); return ret; } void g3_draw_htl_line(vec3d *start, vec3d *end) { if (Cmdline_nohtl) return; gr_draw_htl_line(start,end); } void g3_draw_htl_sphere(vec3d* position, float radius) { if (Cmdline_nohtl) return; g3_start_instance_matrix(position, &vmd_identity_matrix, true); gr_draw_htl_sphere(radius); g3_done_instance(true); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++// //flash ball stuff void flash_ball::initialize(int number, float min_ray_width, float max_ray_width, vec3d* dir, vec3d*pcenter, float outer, float inner, ubyte max_r, ubyte max_g, ubyte max_b, ubyte min_r, ubyte min_g, ubyte min_b) { if(number < 1) return; center = *pcenter; if(n_rays < number){ if(ray)vm_free(ray); ray = (flash_beam*)vm_malloc(sizeof(flash_beam)*number); n_rays = number; } int i; for(i = 0; i= PI2){ //random sphere vec3d start, end; vm_vec_rand_vec_quick(&start); vm_vec_rand_vec_quick(&end); ray[i].start = start; ray[i].end = end; }else{ //random cones vec3d start, end; vm_vec_random_cone(&start, dir, outer, inner); vm_vec_random_cone(&end, dir, outer, inner); ray[i].start = start; ray[i].end = end; } if(max_ray_width == 0.0f)ray[i].width=min_ray_width; else ray[i].width = frand_range(min_ray_width, max_ray_width); } } #define uw(p) (*((uint *) (p))) #define w(p) (*((int *) (p))) #define wp(p) ((int *) (p)) #define vp(p) ((vec3d *) (p)) #define fl(p) (*((float *) (p))) void flash_ball::defpoint(int off, ubyte *bsp_data) { int n; // off+=4; int nverts = w(off+bsp_data+8); int offset = w(off+bsp_data+16); // int next_norm = 0; ubyte * normcount = off+bsp_data+20; vec3d *src = vp(off+bsp_data+offset); if(n_rays < nverts){ if(ray)vm_free(ray); ray = (flash_beam*)vm_malloc(sizeof(flash_beam)*nverts); n_rays = nverts; } { vec3d temp; for (n=0; n= PI2){ //random sphere vec3d end; vm_vec_rand_vec_quick(&end); ray[i].end = end; }else{ //random cones vec3d end; vm_vec_random_cone(&end, dir, outer, inner); ray[i].end = end; } if(max_ray_width == 0.0f)ray[i].width=min_ray_width; else ray[i].width = frand_range(min_ray_width, max_ray_width); } } //rad how wide the ball should be //intinsity how visable it should be //life how far along from start to end should it be void flash_ball::render(float rad, float intinsity, float life){ flash_ball::batcher.allocate(n_rays); for(int i = 0; i