mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 04:31:34 -10:00
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
3010 lines
71 KiB
C++
3010 lines
71 KiB
C++
/*
|
|
* 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.46 $
|
|
* $Date: 2005-10-28 14:45:55 $
|
|
* $Author: taylor $
|
|
*
|
|
* 3D rendering primitives
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* 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"
|
|
|
|
|
|
//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;i<nv;i++){
|
|
if (!(pointlist[i]->flags&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;
|
|
}
|
|
|
|
// if we have too many verts to stick into Vbuf0 then bail out and don't draw anything
|
|
if ( nv > TMAP_MAX_VERTS ) {
|
|
Int3();
|
|
return 1;
|
|
}
|
|
|
|
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;i<nv;i++) {
|
|
vertex *p;
|
|
|
|
p = bufptr[i] = pointlist[i];
|
|
|
|
cc.cc_and &= p->codes;
|
|
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;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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;i<nv;i++)
|
|
if (bufptr[i]->flags & PF_TEMP_POINT)
|
|
free_temp_point(bufptr[i]);
|
|
|
|
} else {
|
|
//now make list of 2d coords (& check for overflow)
|
|
|
|
for (i=0;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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;i<nv;i++){
|
|
if (!(pointlist[i]->flags&PF_PROJECTED))g3_project_vertex(pointlist[i]);
|
|
}
|
|
gr_tmapper( nv, pointlist, tmap_flags );
|
|
return 0;
|
|
}
|
|
|
|
if ( nv > TMAP_MAX_VERTS ) {
|
|
Int3();
|
|
return 1;
|
|
}
|
|
|
|
cc.cc_or = 0; cc.cc_and = 0xff;
|
|
|
|
bufptr = Vbuf0;
|
|
|
|
for (i=0;i<nv;i++) {
|
|
vertex *p;
|
|
|
|
p = bufptr[i] = pointlist[i];
|
|
|
|
cc.cc_and &= p->codes;
|
|
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;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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; i<nv-1; i++){
|
|
g3_draw_line(bufptr[i], bufptr[i+1]);
|
|
}
|
|
g3_draw_line(bufptr[0], bufptr[i]);
|
|
*/
|
|
}
|
|
|
|
free_points:
|
|
;
|
|
|
|
for (i=0;i<nv;i++){
|
|
if (bufptr[i]->flags & PF_TEMP_POINT){
|
|
free_temp_point(bufptr[i]);
|
|
}
|
|
}
|
|
} else {
|
|
//now make list of 2d coords (& check for overflow)
|
|
|
|
for (i=0;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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; i<nv-1; i++){
|
|
g3_draw_line(bufptr[i], bufptr[i+1]);
|
|
}
|
|
g3_draw_line(bufptr[0], bufptr[i]);
|
|
*/
|
|
}
|
|
return 0; //say it drew
|
|
}
|
|
|
|
//draw a sortof sphere - i.e., the 2d radius is proportional to the 3d
|
|
//radius, but not to the distance from the eye
|
|
int g3_draw_sphere(vertex *pnt,float rad)
|
|
{
|
|
Assert( G3_count == 1 );
|
|
|
|
if (! (pnt->codes & 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_batched(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];
|
|
//unused variables that were there for some reason
|
|
// matrix m;
|
|
// vm_set_identity(&m);
|
|
|
|
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
|
|
}
|
|
|
|
vertex *P = batch_get_block(6, tmap_flags);
|
|
|
|
//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;
|
|
|
|
memcpy(&P[4], &P[2], sizeof(vertex));
|
|
memcpy(&P[5], &P[0], sizeof(vertex));
|
|
|
|
/*
|
|
gr_set_cull(0);
|
|
g3_draw_poly(4,ptlist,tmap_flags);
|
|
gr_set_cull(1);
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
int g3_draw_bitmap_3d(vertex *pnt,int orient, float rad,uint tmap_flags, float depth)
|
|
{
|
|
// Redirect for batching!
|
|
if(Cmdline_batch_3dunlit && tmap_flags & TMAP_HTL_3DU_BATCH)
|
|
{
|
|
return g3_draw_bitmap_3d_batched(pnt,orient, rad,tmap_flags, 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
|
|
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 <resolution; i++){
|
|
s = (1.0f - (float(i-1)/res))/6.5f;
|
|
// total +=s;
|
|
float d = (float(i)/res);
|
|
g3_draw_bitmap_3d_v(pnt,orient, rad, tmap_flags, depth * d, s);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
//draws a bitmap with the specified 3d width & height
|
|
//returns 1 if off screen, 0 if drew
|
|
// Orient
|
|
int g3_draw_bitmap(vertex *pnt,int orient, float rad,uint tmap_flags, float depth)
|
|
{
|
|
if(!Cmdline_nohtl)
|
|
{
|
|
bool gr_d3d_particle_set(vertex *pos, int bitmap_id, float size);
|
|
|
|
#ifdef _WIN32
|
|
if((tmap_flags & TMAP_HTL_PARTICLE) && gr_screen.mode == GR_DIRECT3D && Cmdline_d3d_particle)
|
|
if(gr_d3d_particle_set(pnt, gr_screen.current_bitmap, rad) == true)
|
|
return 0;
|
|
#endif
|
|
|
|
if(tmap_flags & TMAP_HTL_3D_UNLIT)
|
|
// return g3_draw_bitmap_3d_volume(pnt, orient, rad, tmap_flags, depth, 10);// just playing with an idea for makeing glows on thrusters less... not... good
|
|
return g3_draw_bitmap_3d(pnt, orient, rad, tmap_flags, depth);
|
|
}
|
|
|
|
vertex va, vb;
|
|
float t,w,h;
|
|
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*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;
|
|
}
|
|
} 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);
|
|
vm_vec_normalize(&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<nv-1; idx++){
|
|
TRIANGLE_AREA(pointlist[0], pointlist[idx], pointlist[idx+1]);
|
|
}
|
|
|
|
// done
|
|
return total_area;
|
|
}
|
|
|
|
// 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
|
|
float g3_draw_poly_constant_sw_area(int nv, vertex **pointlist, uint tmap_flags, float constant_sw, float area)
|
|
{
|
|
int i;
|
|
vertex **bufptr;
|
|
ccodes cc;
|
|
float p_area = 0.0f;
|
|
|
|
Assert( G3_count == 1 );
|
|
|
|
if ( nv > TMAP_MAX_VERTS ) {
|
|
Int3();
|
|
return 0.0f;
|
|
}
|
|
|
|
cc.cc_or = 0;
|
|
cc.cc_and = 0xff;
|
|
|
|
bufptr = Vbuf0;
|
|
|
|
for (i=0;i<nv;i++) {
|
|
vertex *p;
|
|
|
|
p = bufptr[i] = pointlist[i];
|
|
|
|
cc.cc_and &= p->codes;
|
|
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;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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;i<nv;i++){
|
|
if (bufptr[i]->flags & PF_TEMP_POINT){
|
|
free_temp_point(bufptr[i]);
|
|
}
|
|
}
|
|
} else {
|
|
//now make list of 2d coords (& check for overflow)
|
|
|
|
for (i=0;i<nv;i++) {
|
|
vertex *p = bufptr[i];
|
|
|
|
if (!(p->flags&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; idx<div_x; idx++){
|
|
for(s_idx=0; s_idx<div_y; s_idx++){
|
|
// stuff texture coords
|
|
v[0].u = ui * float(idx);
|
|
v[0].v = vi * float(s_idx);
|
|
v[0].spec_r=v[0].spec_g=v[0].spec_b=0;
|
|
|
|
v[1].u = ui * float(idx+1);
|
|
v[1].v = vi * float(s_idx);
|
|
v[1].spec_r=v[1].spec_g=v[1].spec_b=0;
|
|
|
|
v[2].u = ui * float(idx+1);
|
|
v[2].v = vi * float(s_idx+1);
|
|
v[2].spec_r=v[2].spec_g=v[2].spec_b=0;
|
|
|
|
|
|
v[3].u = ui * float(idx);
|
|
v[3].v = vi * float(s_idx+1);
|
|
v[3].spec_r=v[3].spec_g=v[3].spec_b=0;
|
|
|
|
// poly 1
|
|
v[0].flags = 0;
|
|
v[1].flags = 0;
|
|
v[2].flags = 0;
|
|
verts[0] = &v[0];
|
|
verts[1] = &v[1];
|
|
verts[2] = &v[2];
|
|
g3_rotate_faraway_vertex(verts[0], &s_points[idx][s_idx]);
|
|
g3_rotate_faraway_vertex(verts[1], &s_points[idx+1][s_idx]);
|
|
g3_rotate_faraway_vertex(verts[2], &s_points[idx+1][s_idx+1]);
|
|
g3_draw_poly(3, verts, tmap_flags);
|
|
|
|
// poly 2
|
|
v[0].flags = 0;
|
|
v[2].flags = 0;
|
|
v[3].flags = 0;
|
|
verts[0] = &v[0];
|
|
verts[1] = &v[2];
|
|
verts[2] = &v[3];
|
|
g3_rotate_faraway_vertex(verts[0], &s_points[idx][s_idx]);
|
|
g3_rotate_faraway_vertex(verts[1], &s_points[idx+1][s_idx+1]);
|
|
g3_rotate_faraway_vertex(verts[2], &s_points[idx][s_idx+1]);
|
|
g3_draw_poly(3, verts, tmap_flags);
|
|
}
|
|
}
|
|
|
|
// turn on culling
|
|
gr_set_cull(1);
|
|
|
|
// restore zbuffer
|
|
gr_zbuffer_set(saved_zbuffer_mode);
|
|
|
|
// return
|
|
return 1;
|
|
}
|
|
|
|
void g3_draw_2d_rect(int x, int y, int w, int h, int r, int g, int b, int a)
|
|
{
|
|
int saved_zbuf;
|
|
vertex v[4];
|
|
vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
|
|
|
|
memset(v,0,sizeof(vertex)*4);
|
|
saved_zbuf = gr_zbuffer_get();
|
|
|
|
// start the frame, no zbuffering, no culling
|
|
if (!Fred_running)
|
|
g3_start_frame(1);
|
|
|
|
gr_zbuffer_set(GR_ZBUFF_NONE);
|
|
gr_set_cull(0);
|
|
|
|
// stuff coords
|
|
v[0].sx = i2fl(x);
|
|
v[0].sy = i2fl(y);
|
|
v[0].sw = 0.0f;
|
|
v[0].u = 0.0f;
|
|
v[0].v = 0.0f;
|
|
v[0].flags = PF_PROJECTED;
|
|
v[0].codes = 0;
|
|
v[0].r = (ubyte)r;
|
|
v[0].g = (ubyte)g;
|
|
v[0].b = (ubyte)b;
|
|
v[0].a = (ubyte)a;
|
|
|
|
v[1].sx = i2fl(x + w);
|
|
v[1].sy = i2fl(y);
|
|
v[1].sw = 0.0f;
|
|
v[1].u = 0.0f;
|
|
v[1].v = 0.0f;
|
|
v[1].flags = PF_PROJECTED;
|
|
v[1].codes = 0;
|
|
v[1].r = (ubyte)r;
|
|
v[1].g = (ubyte)g;
|
|
v[1].b = (ubyte)b;
|
|
v[1].a = (ubyte)a;
|
|
|
|
v[2].sx = i2fl(x + w);
|
|
v[2].sy = i2fl(y + h);
|
|
v[2].sw = 0.0f;
|
|
v[2].u = 0.0f;
|
|
v[2].v = 0.0f;
|
|
v[2].flags = PF_PROJECTED;
|
|
v[2].codes = 0;
|
|
v[2].r = (ubyte)r;
|
|
v[2].g = (ubyte)g;
|
|
v[2].b = (ubyte)b;
|
|
v[2].a = (ubyte)a;
|
|
|
|
v[3].sx = i2fl(x);
|
|
v[3].sy = i2fl(y + h);
|
|
v[3].sw = 0.0f;
|
|
v[3].u = 0.0f;
|
|
v[3].v = 0.0f;
|
|
v[3].flags = PF_PROJECTED;
|
|
v[3].codes = 0;
|
|
v[3].r = (ubyte)r;
|
|
v[3].g = (ubyte)g;
|
|
v[3].b = (ubyte)b;
|
|
v[3].a = (ubyte)a;
|
|
|
|
// draw the polys
|
|
g3_draw_poly_constant_sw(4, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_FLAG_ALPHA, 0.1f);
|
|
|
|
if (!Fred_running)
|
|
g3_end_frame();
|
|
|
|
|
|
// restore zbuffer and culling
|
|
gr_zbuffer_set(saved_zbuf);
|
|
gr_set_cull(1);
|
|
}
|
|
|
|
// draw a 2d bitmap on a poly
|
|
int g3_draw_2d_poly_bitmap(int x, int y, int w, int h, uint additional_tmap_flags)
|
|
{
|
|
int ret;
|
|
int saved_zbuffer_mode;
|
|
vertex v[4];
|
|
vertex *vertlist[4] = { &v[0], &v[1], &v[2], &v[3] };
|
|
memset(v,0,sizeof(vertex)*4);
|
|
|
|
g3_start_frame(1);
|
|
|
|
// turn off zbuffering
|
|
saved_zbuffer_mode = gr_zbuffer_get();
|
|
gr_zbuffer_set(GR_ZBUFF_NONE);
|
|
|
|
// stuff coords
|
|
v[0].sx = (float)x;
|
|
v[0].sy = (float)y;
|
|
v[0].sw = 0.0f;
|
|
v[0].u = 0.0f;
|
|
v[0].v = 0.0f;
|
|
v[0].flags = PF_PROJECTED;
|
|
v[0].codes = 0;
|
|
|
|
v[1].sx = (float)(x + w);
|
|
v[1].sy = (float)y;
|
|
v[1].sw = 0.0f;
|
|
v[1].u = 1.0f;
|
|
v[1].v = 0.0f;
|
|
v[1].flags = PF_PROJECTED;
|
|
v[1].codes = 0;
|
|
|
|
v[2].sx = (float)(x + w);
|
|
v[2].sy = (float)(y + h);
|
|
v[2].sw = 0.0f;
|
|
v[2].u = 1.0f;
|
|
v[2].v = 1.0f;
|
|
v[2].flags = PF_PROJECTED;
|
|
v[2].codes = 0;
|
|
|
|
v[3].sx = (float)x;
|
|
v[3].sy = (float)(y + h);
|
|
v[3].sw = 0.0f;
|
|
v[3].u = 0.0f;
|
|
v[3].v = 1.0f;
|
|
v[3].flags = PF_PROJECTED;
|
|
v[3].codes = 0;
|
|
|
|
/*
|
|
v[0].u = 0.5f / i2fl(bw);
|
|
v[0].v = 0.5f / i2fl(bh);
|
|
|
|
v[1].u = 1.0f + (0.5f / i2fl(bw));
|
|
v[1].v = 0.0f + (0.5f / i2fl(bh));
|
|
|
|
v[2].u = 1.0f + (0.5f / i2fl(bw));
|
|
v[2].v = 1.0f + (0.5f / i2fl(bh));
|
|
|
|
v[3].u = 0.0f + (0.5f / i2fl(bw));
|
|
v[3].v = 1.0f + (0.5f / i2fl(bh));
|
|
*/
|
|
|
|
// no filtering
|
|
gr_filter_set(0);
|
|
|
|
// set debrief
|
|
ret = g3_draw_poly_constant_sw(4, vertlist, TMAP_FLAG_TEXTURED | additional_tmap_flags, 0.1f);
|
|
|
|
g3_end_frame();
|
|
|
|
gr_zbuffer_set(saved_zbuffer_mode);
|
|
|
|
// put filtering back on
|
|
gr_filter_set(1);
|
|
|
|
return ret;
|
|
}
|
|
|
|
vertex *bitmap_2d_poly_list=NULL;
|
|
vertex **bitmap_2d_poly_vertlist=NULL;
|
|
int bitmap_2d_poly_list_size=0;
|
|
|
|
void bm_list_shutdown(){
|
|
if(bitmap_2d_poly_list)delete[]bitmap_2d_poly_list;
|
|
if(bitmap_2d_poly_vertlist)delete[]bitmap_2d_poly_vertlist;
|
|
}
|
|
|
|
int g3_draw_2d_poly_bitmap_list(bitmap_2d_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; i<n_bm;i++){
|
|
// stuff coords
|
|
|
|
//tri one
|
|
vertex *V = &bitmap_2d_poly_list[i*6];
|
|
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;
|
|
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; i<n_bm;i++){
|
|
// stuff coords
|
|
|
|
bitmap_2d_list* b = &b_list[i].screen_rect;
|
|
texture_rect_list* t = &b_list[i].texture_rect;
|
|
//tri one
|
|
vertex *V = &bitmap_2d_poly_list[i*6];
|
|
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;
|
|
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::initalise(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<n_rays; i++){
|
|
//colors
|
|
if(min_r != 255){
|
|
ray[i].start.r = (rand()%(max_r-min_r))+min_r;
|
|
}else{
|
|
ray[i].start.r = 255;
|
|
}
|
|
if(min_g != 255){
|
|
ray[i].start.g = (rand()%(max_g-min_g))+min_g;
|
|
}else{
|
|
ray[i].start.g = 255;
|
|
}
|
|
if(min_b != 255){
|
|
ray[i].start.b = (rand()%(max_b-min_b))+min_b;
|
|
}else{
|
|
ray[i].start.b = 255;
|
|
}
|
|
|
|
//rays
|
|
if(dir == &vmd_zero_vector || outer >= 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<nverts; n++ ) {
|
|
|
|
temp = *src;
|
|
vm_vec_sub2(&temp, ¢er);
|
|
vm_vec_normalize(&temp);
|
|
ray[n].start = temp;
|
|
|
|
src++; // move to normal
|
|
|
|
src+=normcount[n];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
#define OP_EOF 0
|
|
#define OP_DEFPOINTS 1
|
|
#define OP_FLATPOLY 2
|
|
#define OP_TMAPPOLY 3
|
|
#define OP_SORTNORM 4
|
|
#define OP_BOUNDBOX 5
|
|
|
|
|
|
void flash_ball::parse_bsp(int offset, ubyte *bsp_data){
|
|
int ID, SIZE;
|
|
|
|
memcpy(&ID, &bsp_data[offset], sizeof(int));
|
|
memcpy(&SIZE, &bsp_data[offset+sizeof(int)], sizeof(int));
|
|
|
|
while(ID!=0){
|
|
switch(ID){
|
|
case OP_EOF:
|
|
return;
|
|
break;
|
|
case OP_DEFPOINTS: defpoint(offset, bsp_data);
|
|
break;
|
|
case OP_SORTNORM:
|
|
break;
|
|
case OP_FLATPOLY:
|
|
break;
|
|
case OP_TMAPPOLY:
|
|
break;
|
|
case OP_BOUNDBOX:
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
offset += SIZE;
|
|
memcpy(&ID, &bsp_data[offset], sizeof(int));
|
|
memcpy(&SIZE, &bsp_data[offset+sizeof(int)], sizeof(int));
|
|
|
|
if(SIZE < 1)ID=OP_EOF;
|
|
}
|
|
}
|
|
|
|
|
|
void flash_ball::initalise(ubyte *bsp_data, 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 ){
|
|
center = *pcenter;
|
|
vm_vec_negate(¢er);
|
|
parse_bsp(0,bsp_data);
|
|
center = vmd_zero_vector;
|
|
|
|
int i;
|
|
for(i = 0; i<n_rays; i++){
|
|
//colors
|
|
if(min_r != 255){
|
|
ray[i].start.r = (rand()%(max_r-min_r))+min_r;
|
|
}else{
|
|
ray[i].start.r = 255;
|
|
}
|
|
if(min_g != 255){
|
|
ray[i].start.g = (rand()%(max_g-min_g))+min_g;
|
|
}else{
|
|
ray[i].start.g = 255;
|
|
}
|
|
if(min_b != 255){
|
|
ray[i].start.b = (rand()%(max_b-min_b))+min_b;
|
|
}else{
|
|
ray[i].start.b = 255;
|
|
}
|
|
|
|
//rays
|
|
if(dir == &vmd_zero_vector || outer >= 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<n_rays; i++){
|
|
vec3d end;
|
|
vm_vec_interp_constant(&end, (vec3d*)&ray[i].start.x, (vec3d*)&ray[i].end.x, life);
|
|
vm_vec_scale(&end, rad);
|
|
vm_vec_add2(&end, ¢er);
|
|
flash_ball::batcher.draw_beam(¢er, &end, ray[i].width*rad, intinsity);
|
|
}
|
|
flash_ball::batcher.render(TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT);
|
|
}
|
|
|
|
geometry_batcher flash_ball::batcher;
|