This commit is contained in:
Literally A Penguin
2024-09-25 15:39:25 -05:00
committed by GitHub
parent e8bd66b89c
commit 0bf99969fd
86 changed files with 51093 additions and 0 deletions

1077
ref_soft/adivtab.h Normal file

File diff suppressed because it is too large Load Diff

181
ref_soft/anorms.h Normal file
View File

@ -0,0 +1,181 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
{-0.525731, 0.000000, 0.850651},
{-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423},
{-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056},
{0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731},
{-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718},
{0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017},
{0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423},
{0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056},
{-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000},
{-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000},
{-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621},
{-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017},
{-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785},
{-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017},
{-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731},
{-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242},
{-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000},
{0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460},
{0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460},
{0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863},
{0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017},
{0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621},
{0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000},
{0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856},
{0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000},
{0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191},
{0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000},
{0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000},
{0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856},
{0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000},
{0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731},
{0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000},
{0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651},
{0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567},
{0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000},
{0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866},
{0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017},
{0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017},
{0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651},
{-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423},
{-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000},
{0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056},
{-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017},
{-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731},
{-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718},
{0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017},
{0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056},
{0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017},
{0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621},
{0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191},
{0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000},
{0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731},
{0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863},
{0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017},
{0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000},
{-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017},
{-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000},
{-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621},
{-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017},
{-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460},
{-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000},
{-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567},
{-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191},
{-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718},
{-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056},
{0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056},
{0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718},
{0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866},
{-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731},
{-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866},
{-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866},
{-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856},
{-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000},
{-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567},
{-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},

121
ref_soft/asm_draw.h Normal file
View File

@ -0,0 +1,121 @@
//
// asm_draw.h
//
// Include file for asm drawing routines.
//
//
// !!! note that this file must match the corresponding C structures at all
// times !!!
//
// !!! if this is changed, it must be changed in r_local.h too !!!
#define NEAR_CLIP 0.01
// !!! if this is changed, it must be changed in r_local.h too !!!
#define CYCLE 128
// espan_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define espan_t_u 0
#define espan_t_v 4
#define espan_t_count 8
#define espan_t_pnext 12
#define espan_t_size 16
// sspan_t structure
// !!! if this is changed, it must be changed in d_local.h too !!!
#define sspan_t_u 0
#define sspan_t_v 4
#define sspan_t_count 8
#define sspan_t_pnext 12
#define sspan_t_size 16
// edge_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define et_u 0
#define et_u_step 4
#define et_prev 8
#define et_next 12
#define et_surfs 16
#define et_nextremove 20
#define et_nearzi 24
#define et_owner 28
#define et_size 32
// surf_t structure
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define SURF_T_SHIFT 6
#define st_next 0
#define st_prev 4
#define st_spans 8
#define st_key 12
#define st_last_u 16
#define st_spanstate 20
#define st_flags 24
#define st_data 28
#define st_entity 32
#define st_nearzi 36
#define st_insubmodel 40
#define st_d_ziorigin 44
#define st_d_zistepu 48
#define st_d_zistepv 52
#define st_pad 56
#define st_size 64
// clipplane_t structure
// !!! if this is changed, it must be changed in r_local.h too !!!
#define cp_normal 0
#define cp_dist 12
#define cp_next 16
#define cp_leftedge 20
#define cp_rightedge 21
#define cp_reserved 22
#define cp_size 24
// medge_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define me_v 0
#define me_cachededgeoffset 4
#define me_size 8
// mvertex_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mv_position 0
#define mv_size 12
// refdef_t structure
// !!! if this is changed, it must be changed in render.h too !!!
#define rd_vrect 0
#define rd_aliasvrect 20
#define rd_vrectright 40
#define rd_vrectbottom 44
#define rd_aliasvrectright 48
#define rd_aliasvrectbottom 52
#define rd_vrectrightedge 56
#define rd_fvrectx 60
#define rd_fvrecty 64
#define rd_fvrectx_adj 68
#define rd_fvrecty_adj 72
#define rd_vrect_x_adj_shift20 76
#define rd_vrectright_adj_shift20 80
#define rd_fvrectright_adj 84
#define rd_fvrectbottom_adj 88
#define rd_fvrectright 92
#define rd_fvrectbottom 96
#define rd_horizontalFieldOfView 100
#define rd_xOrigin 104
#define rd_yOrigin 108
#define rd_vieworg 112
#define rd_viewangles 124
#define rd_ambientlight 136
#define rd_size 140
// mtriangle_t structure
// !!! if this is changed, it must be changed in model.h too !!!
#define mtri_facesfront 0
#define mtri_vertindex 4
#define mtri_size 16 // !!! if this changes, array indexing in !!!
// !!! d_polysa.s must be changed to match !!!
#define mtri_shift 4

116
ref_soft/block16.inc Normal file
View File

@ -0,0 +1,116 @@
LEnter16_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch0:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch1:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch2:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch3:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch4:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch5:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch6:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch7:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter8_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch8:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch9:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch10:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch11:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter4_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch12:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch13:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter2_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch14:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch15:
mov ds:word ptr[2+edi],cx
add edi,04h

116
ref_soft/block8.inc Normal file
View File

@ -0,0 +1,116 @@
LEnter16_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch0:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch1:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch2:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch3:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch4:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch5:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch6:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch7:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter8_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch8:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch9:
mov ds:word ptr[2+edi],cx
add edi,04h
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch10:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch11:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter4_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch12:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch13:
mov ds:word ptr[2+edi],cx
add edi,04h
LEnter2_16:
mov al,ds:byte ptr[esi]
mov cl,ds:byte ptr[esi+ebx]
mov ah,dh
add edx,ebp
mov ch,dh
lea esi,ds:dword ptr[esi+ebx*2]
mov ax,ds:word ptr[12345678h+eax*2]
LBPatch14:
add edx,ebp
mov ds:word ptr[edi],ax
mov cx,ds:word ptr[12345678h+ecx*2]
LBPatch15:
mov ds:word ptr[2+edi],cx
add edi,04h

81
ref_soft/d_if.inc Normal file
View File

@ -0,0 +1,81 @@
;
; d_ifacea.h
;
; Include file for asm driver interface.
;
;
; !!! note that this file must match the corresponding C structures in
; d_iface.h at all times !!!
;
; !!! if this is changed, it must be changed in r_shared.h too !!!
ALIAS_ONSEAM equ 00020h
; !!! if this is changed, it must be changed in d_iface.h too !!!
TURB_TEX_SIZE equ 64
; !!! if this is changed, it must be changed in d_iface.h too !!!
CYCLE equ 128
; !!! if this is changed, it must be changed in r_shared.h too !!!
MAXHEIGHT equ 1024
; !!! if this is changed, it must be changed in quakedef.h too !!!
CACHE_SIZE equ 32
; particle_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
; driver-usable fields
pt_org equ 0
pt_color equ 12
; drivers never touch the following fields
pt_next equ 16
pt_vel equ 20
pt_ramp equ 32
pt_die equ 36
pt_type equ 40
pt_size equ 44
PARTICLE_Z_CLIP equ 8.0
; finalvert_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
fv_v equ 0 ; !!! if this is moved, cases where the !!!
; !!! address of this field is pushed in !!!
; !!! d_polysa.s must be changed !!!
fv_flags equ 24
fv_reserved equ 28
fv_size equ 32
fv_shift equ 5
; stvert_t structure
; !!! if this is changed, it must be changed in modelgen.h too !!!
stv_onseam equ 0
stv_s equ 4
stv_t equ 8
stv_size equ 12
; trivertx_t structure
; !!! if this is changed, it must be changed in modelgen.h too !!!
tv_v equ 0
tv_lightnormalindex equ 3
tv_size equ 4
; affinetridesc_t structure
; !!! if this is changed, it must be changed in d_iface.h too !!!
atd_pskin equ 0
atd_pskindesc equ 4
atd_skinwidth equ 8
atd_skinheight equ 12
atd_ptriangles equ 16
atd_pfinalverts equ 20
atd_numtriangles equ 24
atd_drawtype equ 28
atd_seamfixupX16 equ 32
atd_do_vis_thresh equ 36
atd_vis_thresh equ 40
atd_size equ 44

76
ref_soft/d_ifacea.h Normal file
View File

@ -0,0 +1,76 @@
//
// d_ifacea.h
//
// Include file for asm driver interface.
//
//
// !!! note that this file must match the corresponding C structures in
// d_iface.h at all times !!!
//
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define CYCLE 128
// !!! if this is changed, it must be changed in r_shared.h too !!!
#define MAXHEIGHT 1200
// !!! if this is changed, it must be changed in qcommon.h too !!!
#define CACHE_SIZE 32 // used to align key data structures
// particle_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
// driver-usable fields
#define pt_org 0
#define pt_color 12
// drivers never touch the following fields
#define pt_next 16
#define pt_vel 20
#define pt_ramp 32
#define pt_die 36
#define pt_type 40
#define pt_size 44
#define PARTICLE_Z_CLIP 8.0
// finalvert_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define fv_v 0 // !!! if this is moved, cases where the !!!
// !!! address of this field is pushed in !!!
// !!! d_polysa.s must be changed !!!
#define fv_flags 24
#define fv_reserved 28
#define fv_size 32
#define fv_shift 5
// stvert_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define stv_onseam 0
#define stv_s 4
#define stv_t 8
#define stv_size 12
// trivertx_t structure
// !!! if this is changed, it must be changed in modelgen.h too !!!
#define tv_v 0
#define tv_lightnormalindex 3
#define tv_size 4
// affinetridesc_t structure
// !!! if this is changed, it must be changed in d_iface.h too !!!
#define atd_pskin 0
#define atd_pskindesc 4
#define atd_skinwidth 8
#define atd_skinheight 12
#define atd_ptriangles 16
#define atd_pfinalverts 20
#define atd_numtriangles 24
#define atd_drawtype 28
#define atd_seamfixupX16 32
#define atd_size 36

435
ref_soft/qasm.inc Normal file
View File

@ -0,0 +1,435 @@
;
; qasm.inc
;
; Include file for asm routines.
;
;
; !!! note that this file must match the corresponding C structures at all
; times !!!
;
; set to 0 to skip all asm code
id386 equ 1
; !!! must be kept the same as in d_iface.h !!!
TRANSPARENT_COLOR equ 255
ifndef GLQUAKE
externdef _d_zistepu:dword
externdef _d_pzbuffer:dword
externdef _d_zistepv:dword
externdef _d_zrowbytes:dword
externdef _d_ziorigin:dword
externdef _r_turb_s:dword
externdef _r_turb_t:dword
externdef _r_turb_pdest:dword
externdef _r_turb_spancount:dword
externdef _r_turb_turb:dword
externdef _r_turb_pbase:dword
externdef _r_turb_sstep:dword
externdef _r_turb_tstep:dword
externdef _r_bmodelactive:dword
externdef _d_sdivzstepu:dword
externdef _d_tdivzstepu:dword
externdef _d_sdivzstepv:dword
externdef _d_tdivzstepv:dword
externdef _d_sdivzorigin:dword
externdef _d_tdivzorigin:dword
externdef _sadjust:dword
externdef _tadjust:dword
externdef _bbextents:dword
externdef _bbextentt:dword
externdef _cacheblock:dword
externdef _d_viewbuffer:dword
externdef _cachewidth:dword
externdef _d_pzbuffer:dword
externdef _d_zrowbytes:dword
externdef _d_zwidth:dword
externdef _d_scantable:dword
externdef _r_lightptr:dword
externdef _r_numvblocks:dword
externdef _prowdestbase:dword
externdef _pbasesource:dword
externdef _r_lightwidth:dword
externdef _lightright:dword
externdef _lightrightstep:dword
externdef _lightdeltastep:dword
externdef _lightdelta:dword
externdef _lightright:dword
externdef _lightdelta:dword
externdef _sourcetstep:dword
externdef _surfrowbytes:dword
externdef _lightrightstep:dword
externdef _lightdeltastep:dword
externdef _r_sourcemax:dword
externdef _r_stepback:dword
externdef _colormap:dword
externdef _blocksize:dword
externdef _sourcesstep:dword
externdef _lightleft:dword
externdef _blockdivshift:dword
externdef _blockdivmask:dword
externdef _lightleftstep:dword
externdef _r_origin:dword
externdef _r_ppn:dword
externdef _r_pup:dword
externdef _r_pright:dword
externdef _ycenter:dword
externdef _xcenter:dword
externdef _d_vrectbottom_particle:dword
externdef _d_vrectright_particle:dword
externdef _d_vrecty:dword
externdef _d_vrectx:dword
externdef _d_pix_shift:dword
externdef _d_pix_min:dword
externdef _d_pix_max:dword
externdef _d_y_aspect_shift:dword
externdef _screenwidth:dword
externdef _r_leftclipped:dword
externdef _r_leftenter:dword
externdef _r_rightclipped:dword
externdef _r_rightenter:dword
externdef _modelorg:dword
externdef _xscale:dword
externdef _r_refdef:dword
externdef _yscale:dword
externdef _r_leftexit:dword
externdef _r_rightexit:dword
externdef _r_lastvertvalid:dword
externdef _cacheoffset:dword
externdef _newedges:dword
externdef _removeedges:dword
externdef _r_pedge:dword
externdef _r_framecount:dword
externdef _r_u1:dword
externdef _r_emitted:dword
externdef _edge_p:dword
externdef _surface_p:dword
externdef _surfaces:dword
externdef _r_lzi1:dword
externdef _r_v1:dword
externdef _r_ceilv1:dword
externdef _r_nearzi:dword
externdef _r_nearzionly:dword
externdef _edge_aftertail:dword
externdef _edge_tail:dword
externdef _current_iv:dword
externdef _edge_head_u_shift20:dword
externdef _span_p:dword
externdef _edge_head:dword
externdef _fv:dword
externdef _edge_tail_u_shift20:dword
externdef _r_apverts:dword
externdef _r_anumverts:dword
externdef _aliastransform:dword
externdef _r_avertexnormals:dword
externdef _r_plightvec:dword
externdef _r_ambientlight:dword
externdef _r_shadelight:dword
externdef _aliasxcenter:dword
externdef _aliasycenter:dword
externdef _a_sstepxfrac:dword
externdef _r_affinetridesc:dword
externdef _acolormap:dword
externdef _d_pcolormap:dword
externdef _r_affinetridesc:dword
externdef _d_sfrac:dword
externdef _d_ptex:dword
externdef _d_pedgespanpackage:dword
externdef _d_tfrac:dword
externdef _d_light:dword
externdef _d_zi:dword
externdef _d_pdest:dword
externdef _d_pz:dword
externdef _d_aspancount:dword
externdef _erroradjustup:dword
externdef _errorterm:dword
externdef _d_xdenom:dword
externdef _r_p0:dword
externdef _r_p1:dword
externdef _r_p2:dword
externdef _a_tstepxfrac:dword
externdef _r_sstepx:dword
externdef _r_tstepx:dword
externdef _a_ststepxwhole:dword
externdef _zspantable:dword
externdef _skintable:dword
externdef _r_zistepx:dword
externdef _erroradjustdown:dword
externdef _d_countextrastep:dword
externdef _ubasestep:dword
externdef _a_ststepxwhole:dword
externdef _a_tstepxfrac:dword
externdef _r_lstepx:dword
externdef _a_spans:dword
externdef _erroradjustdown:dword
externdef _d_pdestextrastep:dword
externdef _d_pzextrastep:dword
externdef _d_sfracextrastep:dword
externdef _d_ptexextrastep:dword
externdef _d_countextrastep:dword
externdef _d_tfracextrastep:dword
externdef _d_lightextrastep:dword
externdef _d_ziextrastep:dword
externdef _d_pdestbasestep:dword
externdef _d_pzbasestep:dword
externdef _d_sfracbasestep:dword
externdef _d_ptexbasestep:dword
externdef _ubasestep:dword
externdef _d_tfracbasestep:dword
externdef _d_lightbasestep:dword
externdef _d_zibasestep:dword
externdef _zspantable:dword
externdef _r_lstepy:dword
externdef _r_sstepy:dword
externdef _r_tstepy:dword
externdef _r_zistepy:dword
externdef _D_PolysetSetEdgeTable:dword
externdef _D_RasterizeAliasPolySmooth:dword
externdef float_point5:dword
externdef Float2ToThe31nd:dword
externdef izistep:dword
externdef izi:dword
externdef FloatMinus2ToThe31nd:dword
externdef float_1:dword
externdef float_particle_z_clip:dword
externdef float_minus_1:dword
externdef float_0:dword
externdef fp_16:dword
externdef fp_64k:dword
externdef fp_1m:dword
externdef fp_1m_minus_1:dword
externdef fp_8 :dword
externdef entryvec_table:dword
externdef advancetable:dword
externdef sstep:dword
externdef tstep:dword
externdef pspantemp:dword
externdef counttemp:dword
externdef jumptemp:dword
externdef reciprocal_table:dword
externdef DP_Count:dword
externdef DP_u:dword
externdef DP_v:dword
externdef DP_32768:dword
externdef DP_Color:dword
externdef DP_Pix:dword
externdef DP_EntryTable:dword
externdef pbase:dword
externdef s:dword
externdef t:dword
externdef sfracf:dword
externdef tfracf:dword
externdef snext:dword
externdef tnext:dword
externdef spancountminus1:dword
externdef zi16stepu:dword
externdef sdivz16stepu:dword
externdef tdivz16stepu:dword
externdef zi8stepu:dword
externdef sdivz8stepu:dword
externdef tdivz8stepu:dword
externdef reciprocal_table_16:dword
externdef entryvec_table_16:dword
externdef fp_64kx64k:dword
externdef pz:dword
externdef spr8entryvec_table:dword
endif
externdef _fpu_ceil_cw:dword
externdef _fpu_chop_cw:dword
externdef _snd_scaletable:dword
externdef _paintbuffer:dword
externdef _snd_linear_count:dword
externdef _snd_p:dword
externdef _snd_vol:dword
externdef _snd_out:dword
externdef _vright:dword
externdef _vup:dword
externdef _vpn:dword
externdef _BOPS_Error:dword
; plane_t structure
; !!! if this is changed, it must be changed in model.h too !!!
; !!! if the size of this is changed, the array lookup in SV_HullPointContents
; must be changed too !!!
pl_normal equ 0
pl_dist equ 12
pl_type equ 16
pl_signbits equ 17
pl_pad equ 18
pl_size equ 20
; hull_t structure
; !!! if this is changed, it must be changed in model.h too !!!
hu_clipnodes equ 0
hu_planes equ 4
hu_firstclipnode equ 8
hu_lastclipnode equ 12
hu_clip_mins equ 16
hu_clip_maxs equ 28
hu_size equ 40
; dnode_t structure
; !!! if this is changed, it must be changed in bspfile.h too !!!
nd_planenum equ 0
nd_children equ 4
nd_mins equ 8
nd_maxs equ 20
nd_firstface equ 32
nd_numfaces equ 36
nd_size equ 40
; sfxcache_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
sfxc_length equ 0
sfxc_loopstart equ 4
sfxc_speed equ 8
sfxc_width equ 12
sfxc_stereo equ 16
sfxc_data equ 20
; channel_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
ch_sfx equ 0
ch_leftvol equ 4
ch_rightvol equ 8
ch_end equ 12
ch_pos equ 16
ch_looping equ 20
ch_entnum equ 24
ch_entchannel equ 28
ch_origin equ 32
ch_dist_mult equ 44
ch_master_vol equ 48
ch_size equ 52
; portable_samplepair_t structure
; !!! if this is changed, it much be changed in sound.h too !!!
psp_left equ 0
psp_right equ 4
psp_size equ 8
; !!! if this is changed, it must be changed in r_local.h too !!!
NEAR_CLIP equ 0.01
; !!! if this is changed, it must be changed in r_local.h too !!!
CYCLE equ 128
; espan_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
espan_t_u equ 0
espan_t_v equ 4
espan_t_count equ 8
espan_t_pnext equ 12
espan_t_size equ 16
; sspan_t structure
; !!! if this is changed, it must be changed in d_local.h too !!!
sspan_t_u equ 0
sspan_t_v equ 4
sspan_t_count equ 8
sspan_t_size equ 12
; spanpackage_t structure
; !!! if this is changed, it must be changed in d_polyset.c too !!!
spanpackage_t_pdest equ 0
spanpackage_t_pz equ 4
spanpackage_t_count equ 8
spanpackage_t_ptex equ 12
spanpackage_t_sfrac equ 16
spanpackage_t_tfrac equ 20
spanpackage_t_light equ 24
spanpackage_t_zi equ 28
spanpackage_t_size equ 32
; edge_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
et_u equ 0
et_u_step equ 4
et_prev equ 8
et_next equ 12
et_surfs equ 16
et_nextremove equ 20
et_nearzi equ 24
et_owner equ 28
et_size equ 32
; surf_t structure
; !!! if this is changed, it must be changed in r_shared.h too !!!
SURF_T_SHIFT equ 6
st_next equ 0
st_prev equ 4
st_spans equ 8
st_key equ 12
st_last_u equ 16
st_spanstate equ 20
st_flags equ 24
st_data equ 28
st_entity equ 32
st_nearzi equ 36
st_insubmodel equ 40
st_d_ziorigin equ 44
st_d_zistepu equ 48
st_d_zistepv equ 52
st_pad equ 56
st_size equ 64
; clipplane_t structure
; !!! if this is changed, it must be changed in r_local.h too !!!
cp_normal equ 0
cp_dist equ 12
cp_next equ 16
cp_leftedge equ 20
cp_rightedge equ 21
cp_reserved equ 22
cp_size equ 24
; medge_t structure
; !!! if this is changed, it must be changed in model.h too !!!
me_v equ 0
me_cachededgeoffset equ 4
me_size equ 8
; mvertex_t structure
; !!! if this is changed, it must be changed in model.h too !!!
mv_position equ 0
mv_size equ 12
; refdef_t structure
; !!! if this is changed, it must be changed in render.h too !!!
rd_vrect equ 0
rd_aliasvrect equ 20
rd_vrectright equ 40
rd_vrectbottom equ 44
rd_aliasvrectright equ 48
rd_aliasvrectbottom equ 52
rd_vrectrightedge equ 56
rd_fvrectx equ 60
rd_fvrecty equ 64
rd_fvrectx_adj equ 68
rd_fvrecty_adj equ 72
rd_vrect_x_adj_shift20 equ 76
rd_vrectright_adj_shift20 equ 80
rd_fvrectright_adj equ 84
rd_fvrectbottom_adj equ 88
rd_fvrectright equ 92
rd_fvrectbottom equ 96
rd_horizontalFieldOfView equ 100
rd_xOrigin equ 104
rd_yOrigin equ 108
rd_vieworg equ 112
rd_viewangles equ 124
rd_ambientlight equ 136
rd_size equ 140
; mtriangle_t structure
; !!! if this is changed, it must be changed in model.h too !!!
mtri_facesfront equ 0
mtri_vertindex equ 4
mtri_size equ 16 ; !!! if this changes, array indexing in !!!
; !!! d_polysa.s must be changed to match !!!
mtri_shift equ 4

323
ref_soft/r_aclip.c Normal file
View File

@ -0,0 +1,323 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_aclip.c: clip routines for drawing Alias models directly to the screen
#include "r_local.h"
static finalvert_t fv[2][8];
void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
/*
================
R_Alias_clip_z
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
================
*/
void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
(pfv1->xyz[2] - pfv0->xyz[2]);
out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
out->xyz[2] = ALIAS_Z_CLIP_PLANE;
out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
R_AliasProjectAndClipTestFinalVert (out);
}
#if !id386
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v )
{
scale = (float)(r_refdef.aliasvrect.x - pfv0->u) /
(pfv1->u - pfv0->u);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrect.x - pfv1->u) /
(pfv0->u - pfv1->u);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
}
}
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if ( pfv0->v >= pfv1->v )
{
scale = (float)(r_refdef.aliasvrectright - pfv0->u ) /
(pfv1->u - pfv0->u );
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrectright - pfv1->u ) /
(pfv0->u - pfv1->u );
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
}
}
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v)
{
scale = (float)(r_refdef.aliasvrect.y - pfv0->v) /
(pfv1->v - pfv0->v);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrect.y - pfv1->v) /
(pfv0->v - pfv1->v);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
}
}
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v)
{
scale = (float)(r_refdef.aliasvrectbottom - pfv0->v) /
(pfv1->v - pfv0->v);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5;
}
else
{
scale = (float)(r_refdef.aliasvrectbottom - pfv1->v) /
(pfv0->v - pfv1->v);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5;
}
}
#endif
int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
{
int i,j,k;
int flags, oldflags;
j = count-1;
k = 0;
for (i=0 ; i<count ; j = i, i++)
{
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
if (flags && oldflags)
continue;
if (oldflags ^ flags)
{
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].u < r_refdef.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v < r_refdef.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].u > r_refdef.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v > r_refdef.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags)
{
out[k] = in[i];
k++;
}
}
return k;
}
/*
================
R_AliasClipTriangle
================
*/
void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
{
int i, k, pingpong;
unsigned clipflags;
// copy vertexes and fix seam texture coordinates
fv[0][0] = *index0;
fv[0][1] = *index1;
fv[0][2] = *index2;
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
if (clipflags & ALIAS_Z_CLIP)
{
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
if (k == 0)
return;
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
}
else
{
pingpong = 0;
k = 3;
}
if (clipflags & ALIAS_LEFT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_RIGHT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_BOTTOM_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_TOP_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
if (k == 0)
return;
pingpong ^= 1;
}
for (i=0 ; i<k ; i++)
{
if (fv[pingpong][i].u < r_refdef.aliasvrect.x)
fv[pingpong][i].u = r_refdef.aliasvrect.x;
else if (fv[pingpong][i].u > r_refdef.aliasvrectright)
fv[pingpong][i].u = r_refdef.aliasvrectright;
if (fv[pingpong][i].v < r_refdef.aliasvrect.y)
fv[pingpong][i].v = r_refdef.aliasvrect.y;
else if (fv[pingpong][i].v > r_refdef.aliasvrectbottom)
fv[pingpong][i].v = r_refdef.aliasvrectbottom;
fv[pingpong][i].flags = 0;
}
// draw triangles
for (i=1 ; i<k-1 ; i++)
{
aliastriangleparms.a = &fv[pingpong][0];
aliastriangleparms.b = &fv[pingpong][i];
aliastriangleparms.c = &fv[pingpong][i+1];
R_DrawTriangle();
}
}

200
ref_soft/r_aclipa.asm Normal file
View File

@ -0,0 +1,200 @@
.386P
.model FLAT
;
; r_aliasa.s
; x86 assembly-language Alias model transform and project code.
;
include qasm.inc
include d_if.inc
if id386
_DATA SEGMENT
Ltemp0 dd 0
Ltemp1 dd 0
_DATA ENDS
_TEXT SEGMENT
pfv0 equ 8+4
pfv1 equ 8+8
outparm equ 8+12
public _R_Alias_clip_bottom
_R_Alias_clip_bottom:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectbottom]
LDoForwardOrBackward:
mov edx,ds:dword ptr[fv_v+4+esi]
mov ecx,ds:dword ptr[fv_v+4+edi]
cmp edx,ecx
jl LDoForward
mov ecx,ds:dword ptr[fv_v+4+esi]
mov edx,ds:dword ptr[fv_v+4+edi]
mov edi,ds:dword ptr[pfv0+esp]
mov esi,ds:dword ptr[pfv1+esp]
LDoForward:
sub ecx,edx
sub eax,edx
mov ds:dword ptr[Ltemp1],ecx
mov ds:dword ptr[Ltemp0],eax
fild ds:dword ptr[Ltemp1]
fild ds:dword ptr[Ltemp0]
mov edx,ds:dword ptr[outparm+esp]
mov eax,2
fdivrp st(1),st(0) ; scale
LDo3Forward:
fild ds:dword ptr[fv_v+0+esi] ; fv0v0 | scale
fild ds:dword ptr[fv_v+0+edi] ; fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+4+esi] ; fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+4+edi] ; fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+8+esi] ; fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 | scale
fild ds:dword ptr[fv_v+8+edi] ; fv1v2 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv0v0 |
; scale
fxch st(5) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0 | fv1v2 |
; scale
fsub st(4),st(0) ; fv0v0 | fv0v2 | fv1v1 | fv0v1 | fv1v0-fv0v0 |
; fv1v2 | scale
fxch st(3) ; fv0v1 | fv0v2 | fv1v1 | fv0v0 | fv1v0-fv0v0 |
; fv1v2 | scale
fsub st(2),st(0) ; fv0v1 | fv0v2 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2 | scale
fxch st(1) ; fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2 | scale
fsub st(5),st(0) ; fv0v2 | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2-fv0v2 | scale
fxch st(6) ; scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; fv1v0-fv0v0 | fv1v2-fv0v2 | fv0v2
fmul st(4),st(0) ; scale | fv0v1 | fv1v1-fv0v1 | fv0v0 |
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
add edi,12
fmul st(2),st(0) ; scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
; (fv1v0-fv0v0)*scale | fv1v2-fv0v2 | fv0v2
add esi,12
add edx,12
fmul st(5),st(0) ; scale | fv0v1 | (fv1v1-fv0v1)*scale | fv0v0 |
; (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
; fv0v2
fxch st(3) ; fv0v0 | fv0v1 | (fv1v1-fv0v1)*scale | scale |
; (fv1v0-fv0v0)*scale | (fv1v2-fv0v2)*scale |
; fv0v2
faddp st(4),st(0) ; fv0v1 | (fv1v1-fv0v1)*scale | scale |
; fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v2
faddp st(1),st(0) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v2
fxch st(4) ; fv0v2 | scale | fv0v0+(fv1v0-fv0v0)*scale |
; (fv1v2-fv0v2)*scale | fv0v1+(fv1v1-fv0v1)*scale
faddp st(3),st(0) ; scale | fv0v0+(fv1v0-fv0v0)*scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v1+(fv1v1-fv0v1)*scale
fxch st(1) ; fv0v0+(fv1v0-fv0v0)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v1+(fv1v1-fv0v1)*scale
fadd ds:dword ptr[float_point5]
fxch st(3) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale |
; fv0v0+(fv1v0-fv0v0)*scale
fadd ds:dword ptr[float_point5]
fxch st(2) ; fv0v2+(fv1v2-fv0v2)*scale | scale |
; fv0v1+(fv1v1-fv0v1)*scale |
; fv0v0+(fv1v0-fv0v0)*scale
fadd ds:dword ptr[float_point5]
fxch st(3) ; fv0v0+(fv1v0-fv0v0)*scale | scale |
; fv0v1+(fv1v1-fv0v1)*scale |
; fv0v2+(fv1v2-fv0v2)*scale
fistp ds:dword ptr[fv_v+0-12+edx] ; scale | fv0v1+(fv1v1-fv0v1)*scale |
; fv0v2+(fv1v2-fv0v2)*scale
fxch st(1) ; fv0v1+(fv1v1-fv0v1)*scale | scale |
; fv0v2+(fv1v2-fv0v2)*scale | scale
fistp ds:dword ptr[fv_v+4-12+edx] ; scale | fv0v2+(fv1v2-fv0v2)*scale
fxch st(1) ; fv0v2+(fv1v2-fv0v2)*sc | scale
fistp ds:dword ptr[fv_v+8-12+edx] ; scale
dec eax
jnz LDo3Forward
fstp st(0)
pop edi
pop esi
ret
public _R_Alias_clip_top
_R_Alias_clip_top:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+4]
jmp LDoForwardOrBackward
public _R_Alias_clip_right
_R_Alias_clip_right:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrectright]
LRightLeftEntry:
mov edx,ds:dword ptr[fv_v+4+esi]
mov ecx,ds:dword ptr[fv_v+4+edi]
cmp edx,ecx
mov edx,ds:dword ptr[fv_v+0+esi]
mov ecx,ds:dword ptr[fv_v+0+edi]
jl LDoForward2
mov ecx,ds:dword ptr[fv_v+0+esi]
mov edx,ds:dword ptr[fv_v+0+edi]
mov edi,ds:dword ptr[pfv0+esp]
mov esi,ds:dword ptr[pfv1+esp]
LDoForward2:
jmp LDoForward
public _R_Alias_clip_left
_R_Alias_clip_left:
push esi
push edi
mov esi,ds:dword ptr[pfv0+esp]
mov edi,ds:dword ptr[pfv1+esp]
mov eax,ds:dword ptr[_r_refdef+rd_aliasvrect+0]
jmp LRightLeftEntry
_TEXT ENDS
endif ;id386
END

1198
ref_soft/r_alias.c Normal file

File diff suppressed because it is too large Load Diff

637
ref_soft/r_bsp.c Normal file
View File

@ -0,0 +1,637 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_bsp.c
#include "r_local.h"
//
// current entity info
//
qboolean insubmodel;
entity_t *currententity;
vec3_t modelorg; // modelorg is the viewpoint reletive to
// the currently rendering entity
vec3_t r_entorigin; // the currently rendering entity in world
// coordinates
float entity_rotation[3][3];
int r_currentbkey;
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
#define MAX_BMODEL_VERTS 500 // 6K
#define MAX_BMODEL_EDGES 1000 // 12K
static mvertex_t *pbverts;
static bedge_t *pbedges;
static int numbverts, numbedges;
static mvertex_t *pfrontenter, *pfrontexit;
static qboolean makeclippededge;
//===========================================================================
/*
================
R_EntityRotate
================
*/
void R_EntityRotate (vec3_t vec)
{
vec3_t tvec;
VectorCopy (vec, tvec);
vec[0] = DotProduct (entity_rotation[0], tvec);
vec[1] = DotProduct (entity_rotation[1], tvec);
vec[2] = DotProduct (entity_rotation[2], tvec);
}
/*
================
R_RotateBmodel
================
*/
void R_RotateBmodel (void)
{
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
// TODO: should use a look-up table
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: could cache lazily, stored in the entity
// TODO: share work with R_SetUpAliasTransform
// yaw
angle = currententity->angles[YAW];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
temp1[0][0] = c;
temp1[0][1] = s;
temp1[0][2] = 0;
temp1[1][0] = -s;
temp1[1][1] = c;
temp1[1][2] = 0;
temp1[2][0] = 0;
temp1[2][1] = 0;
temp1[2][2] = 1;
// pitch
angle = currententity->angles[PITCH];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
temp2[0][0] = c;
temp2[0][1] = 0;
temp2[0][2] = -s;
temp2[1][0] = 0;
temp2[1][1] = 1;
temp2[1][2] = 0;
temp2[2][0] = s;
temp2[2][1] = 0;
temp2[2][2] = c;
R_ConcatRotations (temp2, temp1, temp3);
// roll
angle = currententity->angles[ROLL];
angle = angle * M_PI*2 / 360;
s = sin(angle);
c = cos(angle);
temp1[0][0] = 1;
temp1[0][1] = 0;
temp1[0][2] = 0;
temp1[1][0] = 0;
temp1[1][1] = c;
temp1[1][2] = s;
temp1[2][0] = 0;
temp1[2][1] = -s;
temp1[2][2] = c;
R_ConcatRotations (temp1, temp3, entity_rotation);
//
// rotate modelorg and the transformation matrix
//
R_EntityRotate (modelorg);
R_EntityRotate (vpn);
R_EntityRotate (vright);
R_EntityRotate (vup);
R_TransformFrustum ();
}
/*
================
R_RecursiveClipBPoly
Clip a bmodel poly down the world bsp tree
================
*/
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
{
bedge_t *psideedges[2], *pnextedge, *ptedge;
int i, side, lastside;
float dist, frac, lastdist;
mplane_t *splitplane, tplane;
mvertex_t *pvert, *plastvert, *ptvert;
mnode_t *pn;
int area;
psideedges[0] = psideedges[1] = NULL;
makeclippededge = false;
// transform the BSP plane into model space
// FIXME: cache these?
splitplane = pnode->plane;
tplane.dist = splitplane->dist -
DotProduct(r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
// clip edges to BSP plane
for ( ; pedges ; pedges = pnextedge)
{
pnextedge = pedges->pnext;
// set the status for the last point as the previous point
// FIXME: cache this stuff somehow?
plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) -
tplane.dist;
if (lastdist > 0)
lastside = 0;
else
lastside = 1;
pvert = pedges->v[1];
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
if (dist > 0)
side = 0;
else
side = 1;
if (side != lastside)
{
// clipped
if (numbverts >= MAX_BMODEL_VERTS)
return;
// generate the clipped vertex
frac = lastdist / (lastdist - dist);
ptvert = &pbverts[numbverts++];
ptvert->position[0] = plastvert->position[0] +
frac * (pvert->position[0] -
plastvert->position[0]);
ptvert->position[1] = plastvert->position[1] +
frac * (pvert->position[1] -
plastvert->position[1]);
ptvert->position[2] = plastvert->position[2] +
frac * (pvert->position[2] -
plastvert->position[2]);
// split into two edges, one on each side, and remember entering
// and exiting points
// FIXME: share the clip edge by having a winding direction flag?
if (numbedges >= (MAX_BMODEL_EDGES - 1))
{
ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[lastside];
psideedges[lastside] = ptedge;
ptedge->v[0] = plastvert;
ptedge->v[1] = ptvert;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[side];
psideedges[side] = ptedge;
ptedge->v[0] = ptvert;
ptedge->v[1] = pvert;
numbedges += 2;
if (side == 0)
{
// entering for front, exiting for back
pfrontenter = ptvert;
makeclippededge = true;
}
else
{
pfrontexit = ptvert;
makeclippededge = true;
}
}
else
{
// add the edge to the appropriate side
pedges->pnext = psideedges[side];
psideedges[side] = pedges;
}
}
// if anything was clipped, reconstitute and add the edges along the clip
// plane to both sides (but in opposite directions)
if (makeclippededge)
{
if (numbedges >= (MAX_BMODEL_EDGES - 2))
{
ri.Con_Printf (PRINT_ALL,"Out of edges for bmodel\n");
return;
}
ptedge = &pbedges[numbedges];
ptedge->pnext = psideedges[0];
psideedges[0] = ptedge;
ptedge->v[0] = pfrontexit;
ptedge->v[1] = pfrontenter;
ptedge = &pbedges[numbedges + 1];
ptedge->pnext = psideedges[1];
psideedges[1] = ptedge;
ptedge->v[0] = pfrontenter;
ptedge->v[1] = pfrontexit;
numbedges += 2;
}
// draw or recurse further
for (i=0 ; i<2 ; i++)
{
if (psideedges[i])
{
// draw if we've reached a non-solid leaf, done if all that's left is a
// solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i];
// we're done with this branch if the node or leaf isn't in the PVS
if (pn->visframe == r_visframecount)
{
if (pn->contents != CONTENTS_NODE)
{
if (pn->contents != CONTENTS_SOLID)
{
if (r_newrefdef.areabits)
{
area = ((mleaf_t *)pn)->area;
if (! (r_newrefdef.areabits[area>>3] & (1<<(area&7)) ) )
continue; // not visible
}
r_currentbkey = ((mleaf_t *)pn)->key;
R_RenderBmodelFace (psideedges[i], psurf);
}
}
else
{
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
psurf);
}
}
}
}
}
/*
================
R_DrawSolidClippedSubmodelPolygons
Bmodel crosses multiple leafs
================
*/
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode)
{
int i, j, lindex;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
mvertex_t bverts[MAX_BMODEL_VERTS];
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
medge_t *pedge, *pedges;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
pedges = pmodel->edges;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (( !(psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
((psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
continue;
// FIXME: use bounding-box-based frustum clipping info?
// copy the edges to bedges, flipping if necessary so always
// clockwise winding
// FIXME: if edges and vertices get caches, these assignments must move
// outside the loop, and overflow checking must be done here
pbverts = bverts;
pbedges = bedges;
numbverts = numbedges = 0;
pbedge = &bedges[numbedges];
numbedges += psurf->numedges;
for (j=0 ; j<psurf->numedges ; j++)
{
lindex = pmodel->surfedges[psurf->firstedge+j];
if (lindex > 0)
{
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
}
else
{
lindex = -lindex;
pedge = &pedges[lindex];
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
}
pbedge[j].pnext = &pbedge[j+1];
}
pbedge[j-1].pnext = NULL; // mark end of edges
if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
R_RecursiveClipBPoly (pbedge, topnode, psurf);
else
R_RenderBmodelFace( pbedge, psurf );
}
}
/*
================
R_DrawSubmodelPolygons
All in one leaf
================
*/
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode)
{
int i;
vec_t dot;
msurface_t *psurf;
int numsurfaces;
mplane_t *pplane;
// FIXME: use bounding-box-based frustum clipping info?
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
numsurfaces = pmodel->nummodelsurfaces;
for (i=0 ; i<numsurfaces ; i++, psurf++)
{
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
r_currentkey = ((mleaf_t *)topnode)->key;
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (psurf, clipflags);
}
}
}
int c_drawnode;
/*
================
R_RecursiveWorldNode
================
*/
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
{
int i, c, side, *pindex;
vec3_t acceptpt, rejectpt;
mplane_t *plane;
msurface_t *surf, **mark;
float d, dot;
mleaf_t *pleaf;
if (node->contents == CONTENTS_SOLID)
return; // solid
if (node->visframe != r_visframecount)
return;
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (clipflags)
{
for (i=0 ; i<4 ; i++)
{
if (! (clipflags & (1<<i)) )
continue; // don't need to clip against it
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the sign bit
// of the floating point values
pindex = pfrustum_indexes[i];
rejectpt[0] = (float)node->minmaxs[pindex[0]];
rejectpt[1] = (float)node->minmaxs[pindex[1]];
rejectpt[2] = (float)node->minmaxs[pindex[2]];
d = DotProduct (rejectpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
if (d <= 0)
return;
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
d = DotProduct (acceptpt, view_clipplanes[i].normal);
d -= view_clipplanes[i].dist;
if (d >= 0)
clipflags &= ~(1<<i); // node is entirely on screen
}
}
c_drawnode++;
// if a leaf node, draw stuff
if (node->contents != -1)
{
pleaf = (mleaf_t *)node;
// check for door connected areas
if (r_newrefdef.areabits)
{
if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
return; // not visible
}
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if (c)
{
do
{
(*mark)->visframe = r_framecount;
mark++;
} while (--c);
}
pleaf->key = r_currentkey;
r_currentkey++; // all bmodels in a leaf share the same key
}
else
{
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane = node->plane;
switch (plane->type)
{
case PLANE_X:
dot = modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (modelorg, plane->normal) - plane->dist;
break;
}
if (dot >= 0)
side = 0;
else
side = 1;
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side], clipflags);
// draw stuff
c = node->numsurfaces;
if (c)
{
surf = r_worldmodel->surfaces + node->firstsurface;
if (dot < -BACKFACE_EPSILON)
{
do
{
if ((surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
R_RenderFace (surf, clipflags);
}
surf++;
} while (--c);
}
else if (dot > BACKFACE_EPSILON)
{
do
{
if (!(surf->flags & SURF_PLANEBACK) &&
(surf->visframe == r_framecount))
{
R_RenderFace (surf, clipflags);
}
surf++;
} while (--c);
}
// all surfaces on the same node share the same sequence number
r_currentkey++;
}
// recurse down the back side
R_RecursiveWorldNode (node->children[!side], clipflags);
}
}
/*
================
R_RenderWorld
================
*/
void R_RenderWorld (void)
{
if (!r_drawworld->value)
return;
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
return;
c_drawnode=0;
// auto cycle the world frame for texture animation
r_worldentity.frame = (int)(r_newrefdef.time*2);
currententity = &r_worldentity;
VectorCopy (r_origin, modelorg);
currentmodel = r_worldmodel;
r_pcurrentvertbase = currentmodel->vertexes;
R_RecursiveWorldNode (currentmodel->nodes, 15);
}

445
ref_soft/r_draw.c Normal file
View File

@ -0,0 +1,445 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// draw.c
#include "r_local.h"
image_t *draw_chars; // 8*8 graphic characters
//=============================================================================
/*
================
Draw_FindPic
================
*/
image_t *Draw_FindPic (char *name)
{
image_t *image;
char fullname[MAX_QPATH];
if (name[0] != '/' && name[0] != '\\')
{
Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
image = R_FindImage (fullname, it_pic);
}
else
image = R_FindImage (name+1, it_pic);
return image;
}
/*
===============
Draw_InitLocal
===============
*/
void Draw_InitLocal (void)
{
draw_chars = Draw_FindPic ("conchars");
}
/*
================
Draw_Char
Draws one 8*8 graphics character
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Char (int x, int y, int num)
{
byte *dest;
byte *source;
int drawline;
int row, col;
num &= 255;
if (num == 32 || num == 32+128)
return;
if (y <= -8)
return; // totally off screen
// if ( ( y + 8 ) >= vid.height )
if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw...
return;
#ifdef PARANOID
if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
if (num < 0 || num > 255)
ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
#endif
row = num>>4;
col = num&15;
source = draw_chars->pixels[0] + (row<<10) + (col<<3);
if (y < 0)
{ // clipped
drawline = 8 + y;
source -= 128*y;
y = 0;
}
else
drawline = 8;
dest = vid.buffer + y*vid.rowbytes + x;
while (drawline--)
{
if (source[0] != TRANSPARENT_COLOR)
dest[0] = source[0];
if (source[1] != TRANSPARENT_COLOR)
dest[1] = source[1];
if (source[2] != TRANSPARENT_COLOR)
dest[2] = source[2];
if (source[3] != TRANSPARENT_COLOR)
dest[3] = source[3];
if (source[4] != TRANSPARENT_COLOR)
dest[4] = source[4];
if (source[5] != TRANSPARENT_COLOR)
dest[5] = source[5];
if (source[6] != TRANSPARENT_COLOR)
dest[6] = source[6];
if (source[7] != TRANSPARENT_COLOR)
dest[7] = source[7];
source += 128;
dest += vid.rowbytes;
}
}
/*
=============
Draw_GetPicSize
=============
*/
void Draw_GetPicSize (int *w, int *h, char *pic)
{
image_t *gl;
gl = Draw_FindPic (pic);
if (!gl)
{
*w = *h = -1;
return;
}
*w = gl->width;
*h = gl->height;
}
/*
=============
Draw_StretchPicImplementation
=============
*/
void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic)
{
byte *dest, *source;
int v, u, sv;
int height;
int f, fstep;
int skip;
if ((x < 0) ||
(x + w > vid.width) ||
(y + h > vid.height))
{
ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
}
height = h;
if (y < 0)
{
skip = -y;
height += y;
y = 0;
}
else
skip = 0;
dest = vid.buffer + y * vid.rowbytes + x;
for (v=0 ; v<height ; v++, dest += vid.rowbytes)
{
sv = (skip + v)*pic->height/h;
source = pic->pixels[0] + sv*pic->width;
if (w == pic->width)
memcpy (dest, source, w);
else
{
f = 0;
fstep = pic->width*0x10000/w;
for (u=0 ; u<w ; u+=4)
{
dest[u] = source[f>>16];
f += fstep;
dest[u+1] = source[f>>16];
f += fstep;
dest[u+2] = source[f>>16];
f += fstep;
dest[u+3] = source[f>>16];
f += fstep;
}
}
}
}
/*
=============
Draw_StretchPic
=============
*/
void Draw_StretchPic (int x, int y, int w, int h, char *name)
{
image_t *pic;
pic = Draw_FindPic (name);
if (!pic)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
return;
}
Draw_StretchPicImplementation (x, y, w, h, pic);
}
/*
=============
Draw_StretchRaw
=============
*/
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
{
image_t pic;
pic.pixels[0] = data;
pic.width = cols;
pic.height = rows;
Draw_StretchPicImplementation (x, y, w, h, &pic);
}
/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, char *name)
{
image_t *pic;
byte *dest, *source;
int v, u;
int tbyte;
int height;
pic = Draw_FindPic (name);
if (!pic)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
return;
}
if ((x < 0) ||
(x + pic->width > vid.width) ||
(y + pic->height > vid.height))
return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
height = pic->height;
source = pic->pixels[0];
if (y < 0)
{
height += y;
source += pic->width*-y;
y = 0;
}
dest = vid.buffer + y * vid.rowbytes + x;
if (!pic->transparent)
{
for (v=0 ; v<height ; v++)
{
memcpy (dest, source, pic->width);
dest += vid.rowbytes;
source += pic->width;
}
}
else
{
if (pic->width & 7)
{ // general
for (v=0 ; v<height ; v++)
{
for (u=0 ; u<pic->width ; u++)
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
dest += vid.rowbytes;
source += pic->width;
}
}
else
{ // unwound
for (v=0 ; v<height ; v++)
{
for (u=0 ; u<pic->width ; u+=8)
{
if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
dest[u] = tbyte;
if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
dest[u+1] = tbyte;
if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
dest[u+2] = tbyte;
if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
dest[u+3] = tbyte;
if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
dest[u+4] = tbyte;
if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
dest[u+5] = tbyte;
if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
dest[u+6] = tbyte;
if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
dest[u+7] = tbyte;
}
dest += vid.rowbytes;
source += pic->width;
}
}
}
}
/*
=============
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h, char *name)
{
int i, j;
byte *psrc;
byte *pdest;
image_t *pic;
int x2;
if (x < 0)
{
w += x;
x = 0;
}
if (y < 0)
{
h += y;
y = 0;
}
if (x + w > vid.width)
w = vid.width - x;
if (y + h > vid.height)
h = vid.height - y;
if (w <= 0 || h <= 0)
return;
pic = Draw_FindPic (name);
if (!pic)
{
ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
return;
}
x2 = x + w;
pdest = vid.buffer + y*vid.rowbytes;
for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
{
psrc = pic->pixels[0] + pic->width * ((i+y)&63);
for (j=x ; j<x2 ; j++)
pdest[j] = psrc[j&63];
}
}
/*
=============
Draw_Fill
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
byte *dest;
int u, v;
if (x+w > vid.width)
w = vid.width - x;
if (y+h > vid.height)
h = vid.height - y;
if (x < 0)
{
w += x;
x = 0;
}
if (y < 0)
{
h += y;
y = 0;
}
if (w < 0 || h < 0)
return;
dest = vid.buffer + y*vid.rowbytes + x;
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
for (u=0 ; u<w ; u++)
dest[u] = c;
}
//=============================================================================
/*
================
Draw_FadeScreen
================
*/
void Draw_FadeScreen (void)
{
int x,y;
byte *pbuf;
int t;
for (y=0 ; y<vid.height ; y++)
{
pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
t = (y & 1) << 1;
for (x=0 ; x<vid.width ; x++)
{
if ((x & 3) != t)
pbuf[x] = 0;
}
}
}

1234
ref_soft/r_draw16.asm Normal file

File diff suppressed because it is too large Load Diff

822
ref_soft/r_drawa.asm Normal file
View File

@ -0,0 +1,822 @@
.386P
.model FLAT
;
; r_drawa.s
; x86 assembly-language edge clipping and emission code
;
include qasm.inc
include d_if.inc
if id386
; !!! if these are changed, they must be changed in r_draw.c too !!!
FULLY_CLIPPED_CACHED equ 080000000h
FRAMECOUNT_MASK equ 07FFFFFFFh
_DATA SEGMENT
Ld0 dd 0.0
Ld1 dd 0.0
Lstack dd 0
Lfp_near_clip dd NEAR_CLIP
Lceilv0 dd 0
Lv dd 0
Lu0 dd 0
Lv0 dd 0
Lzi0 dd 0
_DATA ENDS
_TEXT SEGMENT
;----------------------------------------------------------------------
; edge clipping code
;----------------------------------------------------------------------
pv0 equ 4+12
pv1 equ 8+12
clip equ 12+12
align 4
public _R_ClipEdge
_R_ClipEdge:
push esi ; preserve register variables
push edi
push ebx
mov ds:dword ptr[Lstack],esp ; for clearing the stack later
; float d0, d1, f;
; mvertex_t clipvert;
mov ebx,ds:dword ptr[clip+esp]
mov esi,ds:dword ptr[pv0+esp]
mov edx,ds:dword ptr[pv1+esp]
; if (clip)
; {
test ebx,ebx
jz Lemit
; do
; {
Lcliploop:
; d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
; d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
fld ds:dword ptr[mv_position+0+esi]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+esi]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+esi]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) ; d0mul2 | d0add0
fld ds:dword ptr[mv_position+0+edx]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+edx]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+edx]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) ; d1mul2 | d1add0 | d0mul2 | d0add0
fxch st(3) ; d0add0 | d1add0 | d0mul2 | d1mul2
faddp st(2),st(0) ; d1add0 | dot0 | d1mul2
faddp st(2),st(0) ; dot0 | dot1
fsub ds:dword ptr[cp_dist+ebx] ; d0 | dot1
fxch st(1) ; dot1 | d0
fsub ds:dword ptr[cp_dist+ebx] ; d1 | d0
fxch st(1)
fstp ds:dword ptr[Ld0]
fstp ds:dword ptr[Ld1]
; if (d0 >= 0)
; {
mov eax,ds:dword ptr[Ld0]
mov ecx,ds:dword ptr[Ld1]
or ecx,eax
js Lp2
; both points are unclipped
Lcontinue:
;
; R_ClipEdge (&clipvert, pv1, clip->next);
; return;
; }
; } while ((clip = clip->next) != NULL);
mov ebx,ds:dword ptr[cp_next+ebx]
test ebx,ebx
jnz Lcliploop
; }
;// add the edge
; R_EmitEdge (pv0, pv1);
Lemit:
;
; set integer rounding to ceil mode, set to single precision
;
; FIXME: do away with by manually extracting integers from floats?
; FIXME: set less often
fldcw ds:word ptr[_fpu_ceil_cw]
; edge_t *edge, *pcheck;
; int u_check;
; float u, u_step;
; vec3_t local, transformed;
; float *world;
; int v, v2, ceilv0;
; float scale, lzi0, u0, v0;
; int side;
; if (r_lastvertvalid)
; {
cmp ds:dword ptr[_r_lastvertvalid],0
jz LCalcFirst
; u0 = r_u1;
; v0 = r_v1;
; lzi0 = r_lzi1;
; ceilv0 = r_ceilv1;
mov eax,ds:dword ptr[_r_lzi1]
mov ecx,ds:dword ptr[_r_u1]
mov ds:dword ptr[Lzi0],eax
mov ds:dword ptr[Lu0],ecx
mov ecx,ds:dword ptr[_r_v1]
mov eax,ds:dword ptr[_r_ceilv1]
mov ds:dword ptr[Lv0],ecx
mov ds:dword ptr[Lceilv0],eax
jmp LCalcSecond
; }
LCalcFirst:
; else
; {
; world = &pv0->position[0];
call near ptr LTransformAndProject ; v0 | lzi0 | u0
fst ds:dword ptr[Lv0]
fxch st(2) ; u0 | lzi0 | v0
fstp ds:dword ptr[Lu0] ; lzi0 | v0
fstp ds:dword ptr[Lzi0] ; v0
; ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
fistp ds:dword ptr[Lceilv0]
; }
LCalcSecond:
; world = &pv1->position[0];
mov esi,edx
call near ptr LTransformAndProject ; v1 | lzi1 | u1
fld ds:dword ptr[Lu0] ; u0 | v1 | lzi1 | u1
fxch st(3) ; u1 | v1 | lzi1 | u0
fld ds:dword ptr[Lzi0] ; lzi0 | u1 | v1 | lzi1 | u0
fxch st(3) ; lzi1 | u1 | v1 | lzi0 | u0
fld ds:dword ptr[Lv0] ; v0 | lzi1 | u1 | v1 | lzi0 | u0
fxch st(3) ; v1 | lzi1 | u1 | v0 | lzi0 | u0
; r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
fist ds:dword ptr[_r_ceilv1]
fldcw ds:word ptr[_fpu_chop_cw] ; put back normal floating-point state
fst ds:dword ptr[_r_v1]
fxch st(4) ; lzi0 | lzi1 | u1 | v0 | v1 | u0
; if (r_lzi1 > lzi0)
; lzi0 = r_lzi1;
fcom st(1)
fnstsw ax
test ah,1
jz LP0
fstp st(0)
fld st(0)
LP0:
fxch st(1) ; lzi1 | lzi0 | u1 | v0 | v1 | u0
fstp ds:dword ptr[_r_lzi1] ; lzi0 | u1 | v0 | v1 | u0
fxch st(1)
fst ds:dword ptr[_r_u1]
fxch st(1)
; if (lzi0 > r_nearzi) // for mipmap finding
; r_nearzi = lzi0;
fcom ds:dword ptr[_r_nearzi]
fnstsw ax
test ah,045h
jnz LP1
fst ds:dword ptr[_r_nearzi]
LP1:
; // for right edges, all we want is the effect on 1/z
; if (r_nearzionly)
; return;
mov eax,ds:dword ptr[_r_nearzionly]
test eax,eax
jz LP2
LPop5AndDone:
mov eax,ds:dword ptr[_cacheoffset]
mov edx,ds:dword ptr[_r_framecount]
cmp eax,07FFFFFFFh
jz LDoPop
and edx,offset FRAMECOUNT_MASK
or edx,offset FULLY_CLIPPED_CACHED
mov ds:dword ptr[_cacheoffset],edx
LDoPop:
fstp st(0) ; u1 | v0 | v1 | u0
fstp st(0) ; v0 | v1 | u0
fstp st(0) ; v1 | u0
fstp st(0) ; u0
fstp st(0)
jmp Ldone
LP2:
; // create the edge
; if (ceilv0 == r_ceilv1)
; return; // horizontal edge
mov ebx,ds:dword ptr[Lceilv0]
mov edi,ds:dword ptr[_edge_p]
mov ecx,ds:dword ptr[_r_ceilv1]
mov edx,edi
mov esi,ds:dword ptr[_r_pedge]
add edx,offset et_size
cmp ebx,ecx
jz LPop5AndDone
mov eax,ds:dword ptr[_r_pedge]
mov ds:dword ptr[et_owner+edi],eax
; side = ceilv0 > r_ceilv1;
;
; edge->nearzi = lzi0;
fstp ds:dword ptr[et_nearzi+edi] ; u1 | v0 | v1 | u0
; if (side == 1)
; {
jc LSide0
LSide1:
; // leading edge (go from p2 to p1)
; u_step = ((u0 - r_u1) / (v0 - r_v1));
fsubp st(3),st(0) ; v0 | v1 | u0-u1
fsub st(0),st(1) ; v0-v1 | v1 | u0-u1
fdivp st(2),st(0) ; v1 | ustep
; r_emitted = 1;
mov ds:dword ptr[_r_emitted],1
; edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
; pretouch next edge
mov eax,ds:dword ptr[edx]
; v2 = ceilv0 - 1;
; v = r_ceilv1;
mov eax,ecx
lea ecx,ds:dword ptr[-1+ebx]
mov ebx,eax
; edge->surfs[0] = 0;
; edge->surfs[1] = surface_p - surfaces;
mov eax,ds:dword ptr[_surface_p]
mov esi,ds:dword ptr[_surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+edi],edx
mov ds:dword ptr[et_surfs+2+edi],eax
sub esi,esi
; u = r_u1 + ((float)v - r_v1) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] ; v | v1 | ustep
fsubrp st(1),st(0) ; v-v1 | ustep
fmul st(0),st(1) ; (v-v1)*ustep | ustep
fadd ds:dword ptr[_r_u1] ; u | ustep
jmp LSideDone
; }
LSide0:
; else
; {
; // trailing edge (go from p1 to p2)
; u_step = ((r_u1 - u0) / (r_v1 - v0));
fsub st(0),st(3) ; u1-u0 | v0 | v1 | u0
fxch st(2) ; v1 | v0 | u1-u0 | u0
fsub st(0),st(1) ; v1-v0 | v0 | u1-u0 | u0
fdivp st(2),st(0) ; v0 | ustep | u0
; r_emitted = 1;
mov ds:dword ptr[_r_emitted],1
; edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
; pretouch next edge
mov eax,ds:dword ptr[edx]
; v = ceilv0;
; v2 = r_ceilv1 - 1;
dec ecx
; edge->surfs[0] = surface_p - surfaces;
; edge->surfs[1] = 0;
mov eax,ds:dword ptr[_surface_p]
mov esi,ds:dword ptr[_surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+2+edi],edx
mov ds:dword ptr[et_surfs+edi],eax
mov esi,1
; u = u0 + ((float)v - v0) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] ; v | v0 | ustep | u0
fsubrp st(1),st(0) ; v-v0 | ustep | u0
fmul st(0),st(1) ; (v-v0)*ustep | ustep | u0
faddp st(2),st(0) ; ustep | u
fxch st(1) ; u | ustep
; }
LSideDone:
; edge->u_step = u_step*0x100000;
; edge->u = u*0x100000 + 0xFFFFF;
fmul ds:dword ptr[fp_1m] ; u*0x100000 | ustep
fxch st(1) ; ustep | u*0x100000
fmul ds:dword ptr[fp_1m] ; ustep*0x100000 | u*0x100000
fxch st(1) ; u*0x100000 | ustep*0x100000
fadd ds:dword ptr[fp_1m_minus_1] ; u*0x100000 + 0xFFFFF | ustep*0x100000
fxch st(1) ; ustep*0x100000 | u*0x100000 + 0xFFFFF
fistp ds:dword ptr[et_u_step+edi] ; u*0x100000 + 0xFFFFF
fistp ds:dword ptr[et_u+edi]
; // we need to do this to avoid stepping off the edges if a very nearly
; // horizontal edge is less than epsilon above a scan, and numeric error
; // causes it to incorrectly extend to the scan, and the extension of the
; // line goes off the edge of the screen
; // FIXME: is this actually needed?
; if (edge->u < r_refdef.vrect_x_adj_shift20)
; edge->u = r_refdef.vrect_x_adj_shift20;
; if (edge->u > r_refdef.vrectright_adj_shift20)
; edge->u = r_refdef.vrectright_adj_shift20;
mov eax,ds:dword ptr[et_u+edi]
mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20]
cmp eax,edx
jl LP4
mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20]
cmp eax,edx
jng LP5
LP4:
mov ds:dword ptr[et_u+edi],edx
mov eax,edx
LP5:
; // sort the edge in normally
; u_check = edge->u;
;
; if (edge->surfs[0])
; u_check++; // sort trailers after leaders
add eax,esi
; if (!newedges[v] || newedges[v]->u >= u_check)
; {
mov esi,ds:dword ptr[_newedges+ebx*4]
test esi,esi
jz LDoFirst
cmp ds:dword ptr[et_u+esi],eax
jl LNotFirst
LDoFirst:
; edge->next = newedges[v];
; newedges[v] = edge;
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[_newedges+ebx*4],edi
jmp LSetRemove
; }
LNotFirst:
; else
; {
; pcheck = newedges[v];
;
; while (pcheck->next && pcheck->next->u < u_check)
; pcheck = pcheck->next;
LFindInsertLoop:
mov edx,esi
mov esi,ds:dword ptr[et_next+esi]
test esi,esi
jz LInsertFound
cmp ds:dword ptr[et_u+esi],eax
jl LFindInsertLoop
LInsertFound:
; edge->next = pcheck->next;
; pcheck->next = edge;
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[et_next+edx],edi
; }
LSetRemove:
; edge->nextremove = removeedges[v2];
; removeedges[v2] = edge;
mov eax,ds:dword ptr[_removeedges+ecx*4]
mov ds:dword ptr[_removeedges+ecx*4],edi
mov ds:dword ptr[et_nextremove+edi],eax
Ldone:
mov esp,ds:dword ptr[Lstack] ; clear temporary variables from stack
pop ebx ; restore register variables
pop edi
pop esi
ret
; at least one point is clipped
Lp2:
test eax,eax
jns Lp1
; else
; {
; // point 0 is clipped
; if (d1 < 0)
; {
mov eax,ds:dword ptr[Ld1]
test eax,eax
jns Lp3
; // both points are clipped
; // we do cache fully clipped edges
; if (!leftclipped)
mov eax,ds:dword ptr[_r_leftclipped]
mov ecx,ds:dword ptr[_r_pedge]
test eax,eax
jnz Ldone
; r_pedge->framecount = r_framecount;
mov eax,ds:dword ptr[_r_framecount]
and eax,offset FRAMECOUNT_MASK
or eax,offset FULLY_CLIPPED_CACHED
mov ds:dword ptr[_cacheoffset],eax
; return;
jmp Ldone
; }
Lp1:
; // point 0 is unclipped
; if (d1 >= 0)
; {
; // both points are unclipped
; continue;
; // only point 1 is clipped
; f = d0 / (d0 - d1);
fld ds:dword ptr[Ld0]
fld ds:dword ptr[Ld1]
fsubr st(0),st(1)
; // we don't cache partially clipped edges
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
fdivp st(1),st(0)
sub esp,offset mv_size ; allocate space for clipvert
; clipvert.position[0] = pv0->position[0] +
; f * (pv1->position[0] - pv0->position[0]);
; clipvert.position[1] = pv0->position[1] +
; f * (pv1->position[1] - pv0->position[1]);
; clipvert.position[2] = pv0->position[2] +
; f * (pv1->position[2] - pv0->position[2]);
fld ds:dword ptr[mv_position+8+edx]
fsub ds:dword ptr[mv_position+8+esi]
fld ds:dword ptr[mv_position+4+edx]
fsub ds:dword ptr[mv_position+4+esi]
fld ds:dword ptr[mv_position+0+edx]
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
; replace pv1 with the clip point
mov edx,esp
mov eax,ds:dword ptr[cp_leftedge+ebx]
test al,al
fmul st(0),st(3)
fxch st(1) ; 1 | 0 | 2
fmul st(0),st(3)
fxch st(2) ; 2 | 0 | 1
fmulp st(3),st(0) ; 0 | 1 | 2
fadd ds:dword ptr[mv_position+0+esi]
fxch st(1) ; 1 | 0 | 2
fadd ds:dword ptr[mv_position+4+esi]
fxch st(2) ; 2 | 0 | 1
fadd ds:dword ptr[mv_position+8+esi]
fxch st(1) ; 0 | 2 | 1
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
fstp ds:dword ptr[mv_position+8+esp] ; 1
fstp ds:dword ptr[mv_position+4+esp]
; if (clip->leftedge)
; {
jz Ltestright
; r_leftclipped = true;
; r_leftexit = clipvert;
mov ds:dword ptr[_r_leftclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_leftexit+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_leftexit+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_leftexit+mv_position+8],eax
jmp Lcontinue
; }
Ltestright:
; else if (clip->rightedge)
; {
test ah,ah
jz Lcontinue
; r_rightclipped = true;
; r_rightexit = clipvert;
mov ds:dword ptr[_r_rightclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_rightexit+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_rightexit+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_rightexit+mv_position+8],eax
; }
;
; R_ClipEdge (pv0, &clipvert, clip->next);
; return;
; }
jmp Lcontinue
; }
Lp3:
; // only point 0 is clipped
; r_lastvertvalid = false;
mov ds:dword ptr[_r_lastvertvalid],0
; f = d0 / (d0 - d1);
fld ds:dword ptr[Ld0]
fld ds:dword ptr[Ld1]
fsubr st(0),st(1)
; // we don't cache partially clipped edges
mov ds:dword ptr[_cacheoffset],07FFFFFFFh
fdivp st(1),st(0)
sub esp,offset mv_size ; allocate space for clipvert
; clipvert.position[0] = pv0->position[0] +
; f * (pv1->position[0] - pv0->position[0]);
; clipvert.position[1] = pv0->position[1] +
; f * (pv1->position[1] - pv0->position[1]);
; clipvert.position[2] = pv0->position[2] +
; f * (pv1->position[2] - pv0->position[2]);
fld ds:dword ptr[mv_position+8+edx]
fsub ds:dword ptr[mv_position+8+esi]
fld ds:dword ptr[mv_position+4+edx]
fsub ds:dword ptr[mv_position+4+esi]
fld ds:dword ptr[mv_position+0+edx]
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2
mov eax,ds:dword ptr[cp_leftedge+ebx]
test al,al
fmul st(0),st(3)
fxch st(1) ; 1 | 0 | 2
fmul st(0),st(3)
fxch st(2) ; 2 | 0 | 1
fmulp st(3),st(0) ; 0 | 1 | 2
fadd ds:dword ptr[mv_position+0+esi]
fxch st(1) ; 1 | 0 | 2
fadd ds:dword ptr[mv_position+4+esi]
fxch st(2) ; 2 | 0 | 1
fadd ds:dword ptr[mv_position+8+esi]
fxch st(1) ; 0 | 2 | 1
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1
fstp ds:dword ptr[mv_position+8+esp] ; 1
fstp ds:dword ptr[mv_position+4+esp]
; replace pv0 with the clip point
mov esi,esp
; if (clip->leftedge)
; {
jz Ltestright2
; r_leftclipped = true;
; r_leftenter = clipvert;
mov ds:dword ptr[_r_leftclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_leftenter+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_leftenter+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_leftenter+mv_position+8],eax
jmp Lcontinue
; }
Ltestright2:
; else if (clip->rightedge)
; {
test ah,ah
jz Lcontinue
; r_rightclipped = true;
; r_rightenter = clipvert;
mov ds:dword ptr[_r_rightclipped],1
mov eax,ds:dword ptr[mv_position+0+esp]
mov ds:dword ptr[_r_rightenter+mv_position+0],eax
mov eax,ds:dword ptr[mv_position+4+esp]
mov ds:dword ptr[_r_rightenter+mv_position+4],eax
mov eax,ds:dword ptr[mv_position+8+esp]
mov ds:dword ptr[_r_rightenter+mv_position+8],eax
; }
jmp Lcontinue
; %esi = vec3_t point to transform and project
; %edx preserved
LTransformAndProject:
; // transform and project
; VectorSubtract (world, modelorg, local);
fld ds:dword ptr[mv_position+0+esi]
fsub ds:dword ptr[_modelorg+0]
fld ds:dword ptr[mv_position+4+esi]
fsub ds:dword ptr[_modelorg+4]
fld ds:dword ptr[mv_position+8+esi]
fsub ds:dword ptr[_modelorg+8]
fxch st(2) ; local[0] | local[1] | local[2]
; TransformVector (local, transformed);
;
; if (transformed[2] < NEAR_CLIP)
; transformed[2] = NEAR_CLIP;
;
; lzi0 = 1.0 / transformed[2];
fld st(0) ; local[0] | local[0] | local[1] | local[2]
fmul ds:dword ptr[_vpn+0] ; zm0 | local[0] | local[1] | local[2]
fld st(1) ; local[0] | zm0 | local[0] | local[1] |
; local[2]
fmul ds:dword ptr[_vright+0] ; xm0 | zm0 | local[0] | local[1] | local[2]
fxch st(2) ; local[0] | zm0 | xm0 | local[1] | local[2]
fmul ds:dword ptr[_vup+0] ; ym0 | zm0 | xm0 | local[1] | local[2]
fld st(3) ; local[1] | ym0 | zm0 | xm0 | local[1] |
; local[2]
fmul ds:dword ptr[_vpn+4] ; zm1 | ym0 | zm0 | xm0 | local[1] |
; local[2]
fld st(4) ; local[1] | zm1 | ym0 | zm0 | xm0 |
; local[1] | local[2]
fmul ds:dword ptr[_vright+4] ; xm1 | zm1 | ym0 | zm0 | xm0 |
; local[1] | local[2]
fxch st(5) ; local[1] | zm1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
fmul ds:dword ptr[_vup+4] ; ym1 | zm1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
fxch st(1) ; zm1 | ym1 | ym0 | zm0 | xm0 |
; xm1 | local[2]
faddp st(3),st(0) ; ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
fxch st(3) ; xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
faddp st(4),st(0) ; ym0 | zm2 | ym1 | xm2 | local[2]
faddp st(2),st(0) ; zm2 | ym2 | xm2 | local[2]
fld st(3) ; local[2] | zm2 | ym2 | xm2 | local[2]
fmul ds:dword ptr[_vpn+8] ; zm3 | zm2 | ym2 | xm2 | local[2]
fld st(4) ; local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
fmul ds:dword ptr[_vright+8] ; xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
fxch st(5) ; local[2] | zm3 | zm2 | ym2 | xm2 | xm3
fmul ds:dword ptr[_vup+8] ; ym3 | zm3 | zm2 | ym2 | xm2 | xm3
fxch st(1) ; zm3 | ym3 | zm2 | ym2 | xm2 | xm3
faddp st(2),st(0) ; ym3 | zm4 | ym2 | xm2 | xm3
fxch st(4) ; xm3 | zm4 | ym2 | xm2 | ym3
faddp st(3),st(0) ; zm4 | ym2 | xm4 | ym3
fxch st(1) ; ym2 | zm4 | xm4 | ym3
faddp st(3),st(0) ; zm4 | xm4 | ym4
fcom ds:dword ptr[Lfp_near_clip]
fnstsw ax
test ah,1
jz LNoClip
fstp st(0)
fld ds:dword ptr[Lfp_near_clip]
LNoClip:
fdivr ds:dword ptr[float_1] ; lzi0 | x | y
fxch st(1) ; x | lzi0 | y
; // FIXME: build x/yscale into transform?
; scale = xscale * lzi0;
; u0 = (xcenter + scale*transformed[0]);
fld ds:dword ptr[_xscale] ; xscale | x | lzi0 | y
fmul st(0),st(2) ; scale | x | lzi0 | y
fmulp st(1),st(0) ; scale*x | lzi0 | y
fadd ds:dword ptr[_xcenter] ; u0 | lzi0 | y
; if (u0 < r_refdef.fvrectx_adj)
; u0 = r_refdef.fvrectx_adj;
; if (u0 > r_refdef.fvrectright_adj)
; u0 = r_refdef.fvrectright_adj;
; FIXME: use integer compares of floats?
fcom ds:dword ptr[_r_refdef+rd_fvrectx_adj]
fnstsw ax
test ah,1
jz LClampP0
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectx_adj]
LClampP0:
fcom ds:dword ptr[_r_refdef+rd_fvrectright_adj]
fnstsw ax
test ah,045h
jnz LClampP1
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectright_adj]
LClampP1:
fld st(1) ; lzi0 | u0 | lzi0 | y
; scale = yscale * lzi0;
; v0 = (ycenter - scale*transformed[1]);
fmul ds:dword ptr[_yscale] ; scale | u0 | lzi0 | y
fmulp st(3),st(0) ; u0 | lzi0 | scale*y
fxch st(2) ; scale*y | lzi0 | u0
fsubr ds:dword ptr[_ycenter] ; v0 | lzi0 | u0
; if (v0 < r_refdef.fvrecty_adj)
; v0 = r_refdef.fvrecty_adj;
; if (v0 > r_refdef.fvrectbottom_adj)
; v0 = r_refdef.fvrectbottom_adj;
; FIXME: use integer compares of floats?
fcom ds:dword ptr[_r_refdef+rd_fvrecty_adj]
fnstsw ax
test ah,1
jz LClampP2
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrecty_adj]
LClampP2:
fcom ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
fnstsw ax
test ah,045h
jnz LClampP3
fstp st(0)
fld ds:dword ptr[_r_refdef+rd_fvrectbottom_adj]
LClampP3:
ret
_TEXT ENDS
endif ;id386
END

1125
ref_soft/r_edge.c Normal file

File diff suppressed because it is too large Load Diff

733
ref_soft/r_edgea.asm Normal file
View File

@ -0,0 +1,733 @@
.386P
.model FLAT
;
; r_edgea.s
; x86 assembly-language edge-processing code.
;
include qasm.inc
if id386
_DATA SEGMENT
Ltemp dd 0
float_1_div_0100000h dd 035800000h ; 1.0/(float)0x100000
float_point_999 dd 0.999
float_1_point_001 dd 1.001
_DATA ENDS
_TEXT SEGMENT
;--------------------------------------------------------------------
edgestoadd equ 4+8 ; note odd stack offsets because of interleaving
edgelist equ 8+12 ; with pushes
public _R_EdgeCodeStart
_R_EdgeCodeStart:
public _R_InsertNewEdges
_R_InsertNewEdges:
push edi
push esi ; preserve register variables
mov edx,ds:dword ptr[edgestoadd+esp]
push ebx
mov ecx,ds:dword ptr[edgelist+esp]
LDoNextEdge:
mov eax,ds:dword ptr[et_u+edx]
mov edi,edx
LContinueSearch:
mov ebx,ds:dword ptr[et_u+ecx]
mov esi,ds:dword ptr[et_next+ecx]
cmp eax,ebx
jle LAddedge
mov ebx,ds:dword ptr[et_u+esi]
mov ecx,ds:dword ptr[et_next+esi]
cmp eax,ebx
jle LAddedge2
mov ebx,ds:dword ptr[et_u+ecx]
mov esi,ds:dword ptr[et_next+ecx]
cmp eax,ebx
jle LAddedge
mov ebx,ds:dword ptr[et_u+esi]
mov ecx,ds:dword ptr[et_next+esi]
cmp eax,ebx
jg LContinueSearch
LAddedge2:
mov edx,ds:dword ptr[et_next+edx]
mov ebx,ds:dword ptr[et_prev+esi]
mov ds:dword ptr[et_next+edi],esi
mov ds:dword ptr[et_prev+edi],ebx
mov ds:dword ptr[et_next+ebx],edi
mov ds:dword ptr[et_prev+esi],edi
mov ecx,esi
cmp edx,0
jnz LDoNextEdge
jmp LDone
align 4
LAddedge:
mov edx,ds:dword ptr[et_next+edx]
mov ebx,ds:dword ptr[et_prev+ecx]
mov ds:dword ptr[et_next+edi],ecx
mov ds:dword ptr[et_prev+edi],ebx
mov ds:dword ptr[et_next+ebx],edi
mov ds:dword ptr[et_prev+ecx],edi
cmp edx,0
jnz LDoNextEdge
LDone:
pop ebx ; restore register variables
pop esi
pop edi
ret
;--------------------------------------------------------------------
predge equ 4+4
public _R_RemoveEdges
_R_RemoveEdges:
push ebx
mov eax,ds:dword ptr[predge+esp]
Lre_loop:
mov ecx,ds:dword ptr[et_next+eax]
mov ebx,ds:dword ptr[et_nextremove+eax]
mov edx,ds:dword ptr[et_prev+eax]
test ebx,ebx
mov ds:dword ptr[et_prev+ecx],edx
jz Lre_done
mov ds:dword ptr[et_next+edx],ecx
mov ecx,ds:dword ptr[et_next+ebx]
mov edx,ds:dword ptr[et_prev+ebx]
mov eax,ds:dword ptr[et_nextremove+ebx]
mov ds:dword ptr[et_prev+ecx],edx
test eax,eax
mov ds:dword ptr[et_next+edx],ecx
jnz Lre_loop
pop ebx
ret
Lre_done:
mov ds:dword ptr[et_next+edx],ecx
pop ebx
ret
;--------------------------------------------------------------------
pedgelist equ 4+4 ; note odd stack offset because of interleaving
; with pushes
public _R_StepActiveU
_R_StepActiveU:
push edi
mov edx,ds:dword ptr[pedgelist+esp]
push esi ; preserve register variables
push ebx
mov esi,ds:dword ptr[et_prev+edx]
LNewEdge:
mov edi,ds:dword ptr[et_u+esi]
LNextEdge:
mov eax,ds:dword ptr[et_u+edx]
mov ebx,ds:dword ptr[et_u_step+edx]
add eax,ebx
mov esi,ds:dword ptr[et_next+edx]
mov ds:dword ptr[et_u+edx],eax
cmp eax,edi
jl LPushBack
mov edi,ds:dword ptr[et_u+esi]
mov ebx,ds:dword ptr[et_u_step+esi]
add edi,ebx
mov edx,ds:dword ptr[et_next+esi]
mov ds:dword ptr[et_u+esi],edi
cmp edi,eax
jl LPushBack2
mov eax,ds:dword ptr[et_u+edx]
mov ebx,ds:dword ptr[et_u_step+edx]
add eax,ebx
mov esi,ds:dword ptr[et_next+edx]
mov ds:dword ptr[et_u+edx],eax
cmp eax,edi
jl LPushBack
mov edi,ds:dword ptr[et_u+esi]
mov ebx,ds:dword ptr[et_u_step+esi]
add edi,ebx
mov edx,ds:dword ptr[et_next+esi]
mov ds:dword ptr[et_u+esi],edi
cmp edi,eax
jnl LNextEdge
LPushBack2:
mov ebx,edx
mov eax,edi
mov edx,esi
mov esi,ebx
LPushBack:
; push it back to keep it sorted
mov ecx,ds:dword ptr[et_prev+edx]
mov ebx,ds:dword ptr[et_next+edx]
; done if the -1 in edge_aftertail triggered this
cmp edx,offset _edge_aftertail
jz LUDone
; pull the edge out of the edge list
mov edi,ds:dword ptr[et_prev+ecx]
mov ds:dword ptr[et_prev+esi],ecx
mov ds:dword ptr[et_next+ecx],ebx
; find out where the edge goes in the edge list
LPushBackLoop:
mov ecx,ds:dword ptr[et_prev+edi]
mov ebx,ds:dword ptr[et_u+edi]
cmp eax,ebx
jnl LPushBackFound
mov edi,ds:dword ptr[et_prev+ecx]
mov ebx,ds:dword ptr[et_u+ecx]
cmp eax,ebx
jl LPushBackLoop
mov edi,ecx
; put the edge back into the edge list
LPushBackFound:
mov ebx,ds:dword ptr[et_next+edi]
mov ds:dword ptr[et_prev+edx],edi
mov ds:dword ptr[et_next+edx],ebx
mov ds:dword ptr[et_next+edi],edx
mov ds:dword ptr[et_prev+ebx],edx
mov edx,esi
mov esi,ds:dword ptr[et_prev+esi]
cmp edx,offset _edge_tail
jnz LNewEdge
LUDone:
pop ebx ; restore register variables
pop esi
pop edi
ret
;--------------------------------------------------------------------
surf equ 4 ; note this is loaded before any pushes
align 4
TrailingEdge:
mov eax,ds:dword ptr[st_spanstate+esi] ; check for edge inversion
dec eax
jnz LInverted
mov ds:dword ptr[st_spanstate+esi],eax
mov ecx,ds:dword ptr[st_insubmodel+esi]
mov edx,ds:dword ptr[12345678h] ; surfaces[1].st_next
LPatch0:
mov eax,ds:dword ptr[_r_bmodelactive]
sub eax,ecx
cmp edx,esi
mov ds:dword ptr[_r_bmodelactive],eax
jnz LNoEmit ; surface isn't on top, just remove
; emit a span (current top going away)
mov eax,ds:dword ptr[et_u+ebx]
shr eax,20 ; iu = integral pixel u
mov edx,ds:dword ptr[st_last_u+esi]
mov ecx,ds:dword ptr[st_next+esi]
cmp eax,edx
jle LNoEmit2 ; iu <= surf->last_u, so nothing to emit
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
sub eax,edx
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
add ebp,offset espan_t_size
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LNoEmit2:
mov ds:dword ptr[st_last_u+ecx],eax ; surf->next->last_u = iu;
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LNoEmit:
mov edx,ds:dword ptr[st_next+esi] ; remove the surface from the surface
mov esi,ds:dword ptr[st_prev+esi] ; stack
mov ds:dword ptr[st_next+esi],edx
mov ds:dword ptr[st_prev+edx],esi
ret
LInverted:
mov ds:dword ptr[st_spanstate+esi],eax
ret
;--------------------------------------------------------------------
; trailing edge only
Lgs_trailing:
push offset Lgs_nextedge
jmp TrailingEdge
public _R_GenerateSpans
_R_GenerateSpans:
push ebp ; preserve caller's stack frame
push edi
push esi ; preserve register variables
push ebx
; clear active surfaces to just the background surface
mov eax,ds:dword ptr[_surfaces]
mov edx,ds:dword ptr[_edge_head_u_shift20]
add eax,offset st_size
; %ebp = span_p throughout
mov ebp,ds:dword ptr[_span_p]
mov ds:dword ptr[_r_bmodelactive],0
mov ds:dword ptr[st_next+eax],eax
mov ds:dword ptr[st_prev+eax],eax
mov ds:dword ptr[st_last_u+eax],edx
mov ebx,ds:dword ptr[_edge_head+et_next] ; edge=edge_head.next
; generate spans
cmp ebx,offset _edge_tail ; done if empty list
jz Lgs_lastspan
Lgs_edgeloop:
mov edi,ds:dword ptr[et_surfs+ebx]
mov eax,ds:dword ptr[_surfaces]
mov esi,edi
and edi,0FFFF0000h
and esi,0FFFFh
jz Lgs_leading ; not a trailing edge
; it has a left surface, so a surface is going away for this span
shl esi,offset SURF_T_SHIFT
add esi,eax
test edi,edi
jz Lgs_trailing
; both leading and trailing
call near ptr TrailingEdge
mov eax,ds:dword ptr[_surfaces]
; ---------------------------------------------------------------
; handle a leading edge
; ---------------------------------------------------------------
Lgs_leading:
shr edi,16-SURF_T_SHIFT
mov eax,ds:dword ptr[_surfaces]
add edi,eax
mov esi,ds:dword ptr[12345678h] ; surf2 = surfaces[1].next;
LPatch2:
mov edx,ds:dword ptr[st_spanstate+edi]
mov eax,ds:dword ptr[st_insubmodel+edi]
test eax,eax
jnz Lbmodel_leading
; handle a leading non-bmodel edge
; don't start a span if this is an inverted span, with the end edge preceding
; the start edge (that is, we've already seen the end edge)
test edx,edx
jnz Lxl_done
; if (surf->key < surf2->key)
; goto newtop;
inc edx
mov eax,ds:dword ptr[st_key+edi]
mov ds:dword ptr[st_spanstate+edi],edx
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jl Lnewtop
; main sorting loop to search through surface stack until insertion point
; found. Always terminates because background surface is sentinel
; do
; {
; surf2 = surf2->next;
; } while (surf->key >= surf2->key);
Lsortloopnb:
mov esi,ds:dword ptr[st_next+esi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jge Lsortloopnb
jmp LInsertAndExit
; handle a leading bmodel edge
align 4
Lbmodel_leading:
; don't start a span if this is an inverted span, with the end edge preceding
; the start edge (that is, we've already seen the end edge)
test edx,edx
jnz Lxl_done
mov ecx,ds:dword ptr[_r_bmodelactive]
inc edx
inc ecx
mov ds:dword ptr[st_spanstate+edi],edx
mov ds:dword ptr[_r_bmodelactive],ecx
; if (surf->key < surf2->key)
; goto newtop;
mov eax,ds:dword ptr[st_key+edi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jl Lnewtop
; if ((surf->key == surf2->key) && surf->insubmodel)
; {
jz Lzcheck_for_newtop
; main sorting loop to search through surface stack until insertion point
; found. Always terminates because background surface is sentinel
; do
; {
; surf2 = surf2->next;
; } while (surf->key > surf2->key);
Lsortloop:
mov esi,ds:dword ptr[st_next+esi]
mov ecx,ds:dword ptr[st_key+esi]
cmp eax,ecx
jg Lsortloop
jne LInsertAndExit
; Do 1/z sorting to see if we've arrived in the right position
mov eax,ds:dword ptr[et_u+ebx]
sub eax,0FFFFFh
mov ds:dword ptr[Ltemp],eax
fild ds:dword ptr[Ltemp]
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
; (1.0 / 0x100000);
fld st(0) ; fu | fu
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
fmul ds:dword ptr[st_d_zistepv+edi] ; fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch st(1) ; fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fmul st(0),st(3) ; fu*surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fxch st(1) ; fu*surf->d_zistepu + surf->d_ziorigin |
; fu*surf2->d_zistepu |
; fv*surf->d_zistepv | fu
faddp st(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[st_d_zistepv+esi] ; fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fld st(2) ; newzi | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[float_point_999] ; newzibottom | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fxch st(2) ; fu*surf2->d_zistepu | fv*surf2->d_zistepv |
; newzibottom | newzi | fu
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
; fv*surf2->d_zistepv | newzibottom | newzi |
; fu
faddp st(1),st(0) ; testzi | newzibottom | newzi | fu
fxch st(1) ; newzibottom | testzi | newzi | fu
; if (newzibottom >= testzi)
; goto Lgotposition;
fcomp st(1) ; testzi | newzi | fu
fxch st(1) ; newzi | testzi | fu
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
fxch st(1) ; testzi | newzitop | fu
fnstsw ax
test ah,001h
jz Lgotposition_fpop3
; if (newzitop >= testzi)
; {
fcomp st(1) ; newzitop | fu
fnstsw ax
test ah,045h
jz Lsortloop_fpop2
; if (surf->d_zistepu >= surf2->d_zistepu)
; goto newtop;
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop| fu
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
fnstsw ax
test ah,001h
jz Lgotposition_fpop2
fstp st(0) ; clear the FPstack
fstp st(0)
mov eax,ds:dword ptr[st_key+edi]
jmp Lsortloop
Lgotposition_fpop3:
fstp st(0)
Lgotposition_fpop2:
fstp st(0)
fstp st(0)
jmp LInsertAndExit
; emit a span (obscures current top)
Lnewtop_fpop3:
fstp st(0)
Lnewtop_fpop2:
fstp st(0)
fstp st(0)
mov eax,ds:dword ptr[st_key+edi] ; reload the sorting key
Lnewtop:
mov eax,ds:dword ptr[et_u+ebx]
mov edx,ds:dword ptr[st_last_u+esi]
shr eax,20 ; iu = integral pixel u
mov ds:dword ptr[st_last_u+edi],eax ; surf->last_u = iu;
cmp eax,edx
jle LInsertAndExit ; iu <= surf->last_u, so nothing to emit
sub eax,edx
mov ds:dword ptr[espan_t_u+ebp],edx ; span->u = surf->last_u;
mov ds:dword ptr[espan_t_count+ebp],eax ; span->count = iu - span->u;
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax ; span->v = current_iv;
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax ; span->pnext = surf->spans;
mov ds:dword ptr[st_spans+esi],ebp ; surf->spans = span;
add ebp,offset espan_t_size
LInsertAndExit:
; insert before surf2
mov ds:dword ptr[st_next+edi],esi ; surf->next = surf2;
mov eax,ds:dword ptr[st_prev+esi]
mov ds:dword ptr[st_prev+edi],eax ; surf->prev = surf2->prev;
mov ds:dword ptr[st_prev+esi],edi ; surf2->prev = surf;
mov ds:dword ptr[st_next+eax],edi ; surf2->prev->next = surf;
; ---------------------------------------------------------------
; leading edge done
; ---------------------------------------------------------------
; ---------------------------------------------------------------
; see if there are any more edges
; ---------------------------------------------------------------
Lgs_nextedge:
mov ebx,ds:dword ptr[et_next+ebx]
cmp ebx,offset _edge_tail
jnz Lgs_edgeloop
; clean up at the right edge
Lgs_lastspan:
; now that we've reached the right edge of the screen, we're done with any
; unfinished surfaces, so emit a span for whatever's on top
mov esi,ds:dword ptr[12345678h] ; surfaces[1].st_next
LPatch3:
mov eax,ds:dword ptr[_edge_tail_u_shift20]
xor ecx,ecx
mov edx,ds:dword ptr[st_last_u+esi]
sub eax,edx
jle Lgs_resetspanstate
mov ds:dword ptr[espan_t_u+ebp],edx
mov ds:dword ptr[espan_t_count+ebp],eax
mov eax,ds:dword ptr[_current_iv]
mov ds:dword ptr[espan_t_v+ebp],eax
mov eax,ds:dword ptr[st_spans+esi]
mov ds:dword ptr[espan_t_pnext+ebp],eax
mov ds:dword ptr[st_spans+esi],ebp
add ebp,offset espan_t_size
; reset spanstate for all surfaces in the surface stack
Lgs_resetspanstate:
mov ds:dword ptr[st_spanstate+esi],ecx
mov esi,ds:dword ptr[st_next+esi]
cmp esi,012345678h ; &surfaces[1]
LPatch4:
jnz Lgs_resetspanstate
; store the final span_p
mov ds:dword ptr[_span_p],ebp
pop ebx ; restore register variables
pop esi
pop edi
pop ebp ; restore the caller's stack frame
ret
; ---------------------------------------------------------------
; 1/z sorting for bmodels in the same leaf
; ---------------------------------------------------------------
align 4
Lxl_done:
inc edx
mov ds:dword ptr[st_spanstate+edi],edx
jmp Lgs_nextedge
align 4
Lzcheck_for_newtop:
mov eax,ds:dword ptr[et_u+ebx]
sub eax,0FFFFFh
mov ds:dword ptr[Ltemp],eax
fild ds:dword ptr[Ltemp]
fmul ds:dword ptr[float_1_div_0100000h] ; fu = (float)(edge->u - 0xFFFFF) *
; (1.0 / 0x100000);
fld st(0) ; fu | fu
fmul ds:dword ptr[st_d_zistepu+edi] ; fu*surf->d_zistepu | fu
fld ds:dword ptr[_fv] ; fv | fu*surf->d_zistepu | fu
fmul ds:dword ptr[st_d_zistepv+edi] ; fv*surf->d_zistepv | fu*surf->d_zistepu | fu
fxch st(1) ; fu*surf->d_zistepu | fv*surf->d_zistepv | fu
fadd ds:dword ptr[st_d_ziorigin+edi] ; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fld ds:dword ptr[st_d_zistepu+esi] ; surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fmul st(0),st(3) ; fu*surf2->d_zistepu |
; fu*surf->d_zistepu + surf->d_ziorigin |
; fv*surf->d_zistepv | fu
fxch st(1) ; fu*surf->d_zistepu + surf->d_ziorigin |
; fu*surf2->d_zistepu |
; fv*surf->d_zistepv | fu
faddp st(2),st(0) ; fu*surf2->d_zistepu | newzi | fu
fld ds:dword ptr[_fv] ; fv | fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[st_d_zistepv+esi] ; fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fld st(2) ; newzi | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fmul ds:dword ptr[float_point_999] ; newzibottom | fv*surf2->d_zistepv |
; fu*surf2->d_zistepu | newzi | fu
fxch st(2) ; fu*surf2->d_zistepu | fv*surf2->d_zistepv |
; newzibottom | newzi | fu
fadd ds:dword ptr[st_d_ziorigin+esi] ; fu*surf2->d_zistepu + surf2->d_ziorigin |
; fv*surf2->d_zistepv | newzibottom | newzi |
; fu
faddp st(1),st(0) ; testzi | newzibottom | newzi | fu
fxch st(1) ; newzibottom | testzi | newzi | fu
; if (newzibottom >= testzi)
; goto newtop;
fcomp st(1) ; testzi | newzi | fu
fxch st(1) ; newzi | testzi | fu
fmul ds:dword ptr[float_1_point_001] ; newzitop | testzi | fu
fxch st(1) ; testzi | newzitop | fu
fnstsw ax
test ah,001h
jz Lnewtop_fpop3
; if (newzitop >= testzi)
; {
fcomp st(1) ; newzitop | fu
fnstsw ax
test ah,045h
jz Lsortloop_fpop2
; if (surf->d_zistepu >= surf2->d_zistepu)
; goto newtop;
fld ds:dword ptr[st_d_zistepu+edi] ; surf->d_zistepu | newzitop | fu
fcomp ds:dword ptr[st_d_zistepu+esi] ; newzitop | fu
fnstsw ax
test ah,001h
jz Lnewtop_fpop2
Lsortloop_fpop2:
fstp st(0) ; clear the FP stack
fstp st(0)
mov eax,ds:dword ptr[st_key+edi]
jmp Lsortloop
public _R_EdgeCodeEnd
_R_EdgeCodeEnd:
;----------------------------------------------------------------------
; Surface array address code patching routine
;----------------------------------------------------------------------
align 4
public _R_SurfacePatch
_R_SurfacePatch:
mov eax,ds:dword ptr[_surfaces]
add eax,offset st_size
mov ds:dword ptr[LPatch4-4],eax
add eax,offset st_next
mov ds:dword ptr[LPatch0-4],eax
mov ds:dword ptr[LPatch2-4],eax
mov ds:dword ptr[LPatch3-4],eax
ret
_TEXT ENDS
endif ;id386
END

617
ref_soft/r_image.c Normal file
View File

@ -0,0 +1,617 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "r_local.h"
#define MAX_RIMAGES 1024
image_t r_images[MAX_RIMAGES];
int numr_images;
/*
===============
R_ImageList_f
===============
*/
void R_ImageList_f (void)
{
int i;
image_t *image;
int texels;
ri.Con_Printf (PRINT_ALL, "------------------\n");
texels = 0;
for (i=0, image=r_images ; i<numr_images ; i++, image++)
{
if (image->registration_sequence <= 0)
continue;
texels += image->width*image->height;
switch (image->type)
{
case it_skin:
ri.Con_Printf (PRINT_ALL, "M");
break;
case it_sprite:
ri.Con_Printf (PRINT_ALL, "S");
break;
case it_wall:
ri.Con_Printf (PRINT_ALL, "W");
break;
case it_pic:
ri.Con_Printf (PRINT_ALL, "P");
break;
default:
ri.Con_Printf (PRINT_ALL, " ");
break;
}
ri.Con_Printf (PRINT_ALL, " %3i %3i : %s\n",
image->width, image->height, image->name);
}
ri.Con_Printf (PRINT_ALL, "Total texel count: %i\n", texels);
}
/*
=================================================================
PCX LOADING
=================================================================
*/
/*
==============
LoadPCX
==============
*/
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
{
byte *raw;
pcx_t *pcx;
int x, y;
int len;
int dataByte, runLength;
byte *out, *pix;
*pic = NULL;
//
// load the file
//
len = ri.FS_LoadFile (filename, (void **)&raw);
if (!raw)
{
ri.Con_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
return;
}
//
// parse the PCX file
//
pcx = (pcx_t *)raw;
pcx->xmin = LittleShort(pcx->xmin);
pcx->ymin = LittleShort(pcx->ymin);
pcx->xmax = LittleShort(pcx->xmax);
pcx->ymax = LittleShort(pcx->ymax);
pcx->hres = LittleShort(pcx->hres);
pcx->vres = LittleShort(pcx->vres);
pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
pcx->palette_type = LittleShort(pcx->palette_type);
raw = &pcx->data;
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8
|| pcx->xmax >= 640
|| pcx->ymax >= 480)
{
ri.Con_Printf (PRINT_ALL, "Bad pcx file %s\n", filename);
return;
}
out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
*pic = out;
pix = out;
if (palette)
{
*palette = malloc(768);
memcpy (*palette, (byte *)pcx + len - 768, 768);
}
if (width)
*width = pcx->xmax+1;
if (height)
*height = pcx->ymax+1;
for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
{
for (x=0 ; x<=pcx->xmax ; )
{
dataByte = *raw++;
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
dataByte = *raw++;
}
else
runLength = 1;
while(runLength-- > 0)
pix[x++] = dataByte;
}
}
if ( raw - (byte *)pcx > len)
{
ri.Con_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename);
free (*pic);
*pic = NULL;
}
ri.FS_FreeFile (pcx);
}
/*
=========================================================
TARGA LOADING
=========================================================
*/
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
/*
=============
LoadTGA
=============
*/
void LoadTGA (char *name, byte **pic, int *width, int *height)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
byte *buf_p;
byte *buffer;
int length;
TargaHeader targa_header;
byte *targa_rgba;
*pic = NULL;
//
// load the file
//
length = ri.FS_LoadFile (name, (void **)&buffer);
if (!buffer)
{
ri.Con_Printf (PRINT_DEVELOPER, "Bad tga file %s\n", name);
return;
}
buf_p = buffer;
targa_header.id_length = *buf_p++;
targa_header.colormap_type = *buf_p++;
targa_header.image_type = *buf_p++;
targa_header.colormap_index = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.colormap_length = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.colormap_size = *buf_p++;
targa_header.x_origin = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.y_origin = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.width = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.height = LittleShort ( *((short *)buf_p) );
buf_p+=2;
targa_header.pixel_size = *buf_p++;
targa_header.attributes = *buf_p++;
if (targa_header.image_type!=2
&& targa_header.image_type!=10)
ri.Sys_Error (ERR_DROP, "LoadTGA: Only type 2 and 10 targa RGB images supported\n");
if (targa_header.colormap_type !=0
|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
ri.Sys_Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
if (width)
*width = columns;
if (height)
*height = rows;
targa_rgba = malloc (numPixels*4);
*pic = targa_rgba;
if (targa_header.id_length != 0)
buf_p += targa_header.id_length; // skip TARGA image comment
if (targa_header.image_type==2) { // Uncompressed, RGB images
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++) {
unsigned char red,green,blue,alphabyte;
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader= *buf_p++;
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
break;
}
for(j=0;j<packetSize;j++) {
*pixbuf++=red;
*pixbuf++=green;
*pixbuf++=blue;
*pixbuf++=alphabyte;
column++;
if (column==columns) { // run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
else { // non run-length packet
for(j=0;j<packetSize;j++) {
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
column++;
if (column==columns) { // pixel packet run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
}
breakOut:;
}
}
ri.FS_FreeFile (buffer);
}
//=======================================================
image_t *R_FindFreeImage (void)
{
image_t *image;
int i;
// find a free image_t
for (i=0, image=r_images ; i<numr_images ; i++,image++)
{
if (!image->registration_sequence)
break;
}
if (i == numr_images)
{
if (numr_images == MAX_RIMAGES)
ri.Sys_Error (ERR_DROP, "MAX_RIMAGES");
numr_images++;
}
image = &r_images[i];
return image;
}
/*
================
GL_LoadPic
================
*/
image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type)
{
image_t *image;
int i, c, b;
image = R_FindFreeImage ();
if (strlen(name) >= sizeof(image->name))
ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
strcpy (image->name, name);
image->registration_sequence = registration_sequence;
image->width = width;
image->height = height;
image->type = type;
c = width*height;
image->pixels[0] = malloc (c);
image->transparent = false;
for (i=0 ; i<c ; i++)
{
b = pic[i];
if (b == 255)
image->transparent = true;
image->pixels[0][i] = b;
}
return image;
}
/*
================
R_LoadWal
================
*/
image_t *R_LoadWal (char *name)
{
miptex_t *mt;
int ofs;
image_t *image;
int size;
ri.FS_LoadFile (name, (void **)&mt);
if (!mt)
{
ri.Con_Printf (PRINT_ALL, "R_LoadWal: can't load %s\n", name);
return r_notexture_mip;
}
image = R_FindFreeImage ();
strcpy (image->name, name);
image->width = LittleLong (mt->width);
image->height = LittleLong (mt->height);
image->type = it_wall;
image->registration_sequence = registration_sequence;
size = image->width*image->height * (256+64+16+4)/256;
image->pixels[0] = malloc (size);
image->pixels[1] = image->pixels[0] + image->width*image->height;
image->pixels[2] = image->pixels[1] + image->width*image->height/4;
image->pixels[3] = image->pixels[2] + image->width*image->height/16;
ofs = LittleLong (mt->offsets[0]);
memcpy ( image->pixels[0], (byte *)mt + ofs, size);
ri.FS_FreeFile ((void *)mt);
return image;
}
/*
===============
R_FindImage
Finds or loads the given image
===============
*/
image_t *R_FindImage (char *name, imagetype_t type)
{
image_t *image;
int i, len;
byte *pic, *palette;
int width, height;
if (!name)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: NULL name");
len = strlen(name);
if (len<5)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad name: %s", name);
// look for it
for (i=0, image=r_images ; i<numr_images ; i++,image++)
{
if (!strcmp(name, image->name))
{
image->registration_sequence = registration_sequence;
return image;
}
}
//
// load the pic from disk
//
pic = NULL;
palette = NULL;
if (!strcmp(name+len-4, ".pcx"))
{
LoadPCX (name, &pic, &palette, &width, &height);
if (!pic)
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s", name);
image = GL_LoadPic (name, pic, width, height, type);
}
else if (!strcmp(name+len-4, ".wal"))
{
image = R_LoadWal (name);
}
else if (!strcmp(name+len-4, ".tga"))
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: can't load %s in software renderer", name);
else
return NULL; // ri.Sys_Error (ERR_DROP, "R_FindImage: bad extension on: %s", name);
if (pic)
free(pic);
if (palette)
free(palette);
return image;
}
/*
===============
R_RegisterSkin
===============
*/
struct image_s *R_RegisterSkin (char *name)
{
return R_FindImage (name, it_skin);
}
/*
================
R_FreeUnusedImages
Any image that was not touched on this registration sequence
will be freed.
================
*/
void R_FreeUnusedImages (void)
{
int i;
image_t *image;
for (i=0, image=r_images ; i<numr_images ; i++, image++)
{
if (image->registration_sequence == registration_sequence)
{
Com_PageInMemory ((byte *)image->pixels[0], image->width*image->height);
continue; // used this sequence
}
if (!image->registration_sequence)
continue; // free texture
if (image->type == it_pic)
continue; // don't free pics
// free it
free (image->pixels[0]); // the other mip levels just follow
memset (image, 0, sizeof(*image));
}
}
/*
===============
R_InitImages
===============
*/
void R_InitImages (void)
{
registration_sequence = 1;
}
/*
===============
R_ShutdownImages
===============
*/
void R_ShutdownImages (void)
{
int i;
image_t *image;
for (i=0, image=r_images ; i<numr_images ; i++, image++)
{
if (!image->registration_sequence)
continue; // free texture
// free it
free (image->pixels[0]); // the other mip levels just follow
memset (image, 0, sizeof(*image));
}
}

442
ref_soft/r_light.c Normal file
View File

@ -0,0 +1,442 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_light.c
#include "r_local.h"
int r_dlightframecount;
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
=============
R_MarkLights
=============
*/
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents != -1)
return;
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
//=====
//PGM
i=light->intensity;
if(i<0)
i=-i;
//PGM
//=====
if (dist > i) // PGM (dist > light->intensity)
{
R_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -i) // PGM (dist < -light->intensity)
{
R_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = r_worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
R_MarkLights (light, bit, node->children[0]);
R_MarkLights (light, bit, node->children[1]);
}
/*
=============
R_PushDlights
=============
*/
void R_PushDlights (model_t *model)
{
int i;
dlight_t *l;
r_dlightframecount = r_framecount;
for (i=0, l = r_newrefdef.dlights ; i<r_newrefdef.num_dlights ; i++, l++)
{
R_MarkLights ( l, 1<<i,
model->nodes + model->firstnode);
}
}
/*
=============================================================================
LIGHT SAMPLING
=============================================================================
*/
vec3_t pointcolor;
mplane_t *lightplane; // used as shadow plane
vec3_t lightspot;
int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
float *scales;
int maps;
float samp;
int r;
if (node->contents != -1)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ( (back < 0) == side)
return RecursiveLightPoint (node->children[side], start, end);
frac = front / (front-back);
mid[0] = start[0] + (end[0] - start[0])*frac;
mid[1] = start[1] + (end[1] - start[1])*frac;
mid[2] = start[2] + (end[2] - start[2])*frac;
if (plane->type < 3) // axial planes
mid[plane->type] = plane->dist;
// go down front side
r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ( (back < 0) == side )
return -1; // didn't hit anuthing
// check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = r_worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags&(SURF_DRAWTURB|SURF_DRAWSKY))
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ( ds > surf->extents[0] || dt > surf->extents[1] )
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
VectorCopy (vec3_origin, pointcolor);
if (lightmap)
{
lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
samp = *lightmap * /* 0.5 * */ (1.0/255); // adjust for gl scale
scales = r_newrefdef.lightstyles[surf->styles[maps]].rgb;
VectorMA (pointcolor, samp, scales, pointcolor);
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
}
}
return 1;
}
// go down back side
return RecursiveLightPoint (node->children[!side], mid, end);
}
/*
===============
R_LightPoint
===============
*/
void R_LightPoint (vec3_t p, vec3_t color)
{
vec3_t end;
float r;
int lnum;
dlight_t *dl;
float light;
vec3_t dist;
float add;
if (!r_worldmodel->lightdata)
{
color[0] = color[1] = color[2] = 1.0;
return;
}
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint (r_worldmodel->nodes, p, end);
if (r == -1)
{
VectorCopy (vec3_origin, color);
}
else
{
VectorCopy (pointcolor, color);
}
//
// add dynamic lights
//
light = 0;
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
{
dl = &r_newrefdef.dlights[lnum];
VectorSubtract (currententity->origin,
dl->origin,
dist);
add = dl->intensity - VectorLength(dist);
add *= (1.0/256);
if (add > 0)
{
VectorMA (color, add, dl->color, color);
}
}
}
//===================================================================
unsigned blocklights[1024]; // allow some very large lightmaps
/*
===============
R_AddDynamicLights
===============
*/
void R_AddDynamicLights (void)
{
msurface_t *surf;
int lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
dlight_t *dl;
int negativeLight; //PGM
surf = r_drawsurf.surf;
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
tex = surf->texinfo;
for (lnum=0 ; lnum<r_newrefdef.num_dlights ; lnum++)
{
if ( !(surf->dlightbits & (1<<lnum) ) )
continue; // not lit by this light
dl = &r_newrefdef.dlights[lnum];
rad = dl->intensity;
//=====
//PGM
negativeLight = 0;
if(rad < 0)
{
negativeLight = 1;
rad = -rad;
}
//PGM
//=====
dist = DotProduct (dl->origin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs(dist);
minlight = 32; // dl->minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
for (i=0 ; i<3 ; i++)
{
impact[i] = dl->origin[i] -
surf->plane->normal[i]*dist;
}
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
local[0] -= surf->texturemins[0];
local[1] -= surf->texturemins[1];
for (t = 0 ; t<tmax ; t++)
{
td = local[1] - t*16;
if (td < 0)
td = -td;
for (s=0 ; s<smax ; s++)
{
sd = local[0] - s*16;
if (sd < 0)
sd = -sd;
if (sd > td)
dist = sd + (td>>1);
else
dist = td + (sd>>1);
//====
//PGM
if(!negativeLight)
{
if (dist < minlight)
blocklights[t*smax + s] += (rad - dist)*256;
}
else
{
if (dist < minlight)
blocklights[t*smax + s] -= (rad - dist)*256;
if(blocklights[t*smax + s] < minlight)
blocklights[t*smax + s] = minlight;
}
//PGM
//====
}
}
}
}
/*
===============
R_BuildLightMap
Combine and scale multiple lightmaps into the 8.8 format in blocklights
===============
*/
void R_BuildLightMap (void)
{
int smax, tmax;
int t;
int i, size;
byte *lightmap;
unsigned scale;
int maps;
msurface_t *surf;
surf = r_drawsurf.surf;
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
size = smax*tmax;
if (r_fullbright->value || !r_worldmodel->lightdata)
{
for (i=0 ; i<size ; i++)
blocklights[i] = 0;
return;
}
// clear to no light
for (i=0 ; i<size ; i++)
blocklights[i] = 0;
// add all the lightmaps
lightmap = surf->samples;
if (lightmap)
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
for (i=0 ; i<size ; i++)
blocklights[i] += lightmap[i] * scale;
lightmap += size; // skip to next lightmap
}
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights ();
// bound, invert, and shift
for (i=0 ; i<size ; i++)
{
t = (int)blocklights[i];
if (t < 0)
t = 0;
t = (255*256 - t) >> (8 - VID_CBITS);
if (t < (1 << 6))
t = (1 << 6);
blocklights[i] = t;
}
}

849
ref_soft/r_local.h Normal file
View File

@ -0,0 +1,849 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include "../client/ref.h"
#define REF_VERSION "SOFT 0.01"
// up / down
#define PITCH 0
// left / right
#define YAW 1
// fall over
#define ROLL 2
/*
skins will be outline flood filled and mip mapped
pics and sprites with alpha will be outline flood filled
pic won't be mip mapped
model skin
sprite frame
wall texture
pic
*/
typedef enum
{
it_skin,
it_sprite,
it_wall,
it_pic,
it_sky
} imagetype_t;
typedef struct image_s
{
char name[MAX_QPATH]; // game path, including extension
imagetype_t type;
int width, height;
qboolean transparent; // true if any 255 pixels in image
int registration_sequence; // 0 = free
byte *pixels[4]; // mip levels
} image_t;
//===================================================================
typedef unsigned char pixel_t;
typedef struct vrect_s
{
int x,y,width,height;
struct vrect_s *pnext;
} vrect_t;
typedef struct
{
pixel_t *buffer; // invisible buffer
pixel_t *colormap; // 256 * VID_GRADES size
pixel_t *alphamap; // 256 * 256 translucency map
int rowbytes; // may be > width if displayed in a window
// can be negative for stupid dibs
int width;
int height;
} viddef_t;
typedef enum
{
rserr_ok,
rserr_invalid_fullscreen,
rserr_invalid_mode,
rserr_unknown
} rserr_t;
extern viddef_t vid;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vrect_t vrect; // subwindow in video for refresh
// FIXME: not need vrect next field here?
vrect_t aliasvrect; // scaled Alias version
int vrectright, vrectbottom; // right & bottom screen coords
int aliasvrectright, aliasvrectbottom; // scaled Alias versions
float vrectrightedge; // rightmost right edge we care about,
// for use in edge list
float fvrectx, fvrecty; // for floating-point compares
float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping
int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20
int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20
float fvrectright_adj, fvrectbottom_adj;
// right and bottom edges, for clamping
float fvrectright; // rightmost edge, for Alias clamping
float fvrectbottom; // bottommost edge, for Alias clamping
float horizontalFieldOfView; // at Z = 1.0, this many X is visible
// 2.0 = 90 degrees
float xOrigin; // should probably always be 0.5
float yOrigin; // between be around 0.3 to 0.5
vec3_t vieworg;
vec3_t viewangles;
int ambientlight;
} oldrefdef_t;
extern oldrefdef_t r_refdef;
#include "r_model.h"
#define CACHE_SIZE 32
/*
====================================================
CONSTANTS
====================================================
*/
#define VID_CBITS 6
#define VID_GRADES (1 << VID_CBITS)
// r_shared.h: general refresh-related stuff shared between the refresh and the
// driver
#define MAXVERTS 64 // max points in a surface polygon
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
// polygon (while processing)
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define MAXHEIGHT 1200
#define MAXWIDTH 1600
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
// be farther away than anything in
// the scene
// d_iface.h: interface header file for rasterization driver modules
#define WARP_WIDTH 320
#define WARP_HEIGHT 240
#define MAX_LBM_HEIGHT 480
#define PARTICLE_Z_CLIP 8.0
// !!! must be kept the same as in quakeasm.h !!!
#define TRANSPARENT_COLOR 0xFF
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define TURB_TEX_SIZE 64 // base turbulent texture size
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
#define CYCLE 128 // turbulent cycle size
#define SCANBUFFERPAD 0x1000
#define DS_SPAN_LIST_END -128
#define NUMSTACKEDGES 2000
#define MINEDGES NUMSTACKEDGES
#define NUMSTACKSURFACES 1000
#define MINSURFACES NUMSTACKSURFACES
#define MAXSPANS 3000
// flags in finalvert_t.flags
#define ALIAS_LEFT_CLIP 0x0001
#define ALIAS_TOP_CLIP 0x0002
#define ALIAS_RIGHT_CLIP 0x0004
#define ALIAS_BOTTOM_CLIP 0x0008
#define ALIAS_Z_CLIP 0x0010
#define ALIAS_XY_CLIP_MASK 0x000F
#define SURFCACHE_SIZE_AT_320X240 1024*768
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
// if bbox is trivially rejected
#define XCENTERING (1.0 / 2.0)
#define YCENTERING (1.0 / 2.0)
#define CLIP_EPSILON 0.001
#define BACKFACE_EPSILON 0.01
// !!! if this is changed, it must be changed in asm_draw.h too !!!
#define NEAR_CLIP 0.01
#define MAXALIASVERTS 2000 // TODO: tune this
#define ALIAS_Z_CLIP_PLANE 4
// turbulence stuff
#define AMP 8*0x10000
#define AMP2 3
#define SPEED 20
/*
====================================================
TYPES
====================================================
*/
typedef struct
{
float u, v;
float s, t;
float zi;
} emitpoint_t;
/*
** if you change this structure be sure to change the #defines
** listed after it!
*/
#define SMALL_FINALVERT 0
#if SMALL_FINALVERT
typedef struct finalvert_s {
short u, v, s, t;
int l;
int zi;
int flags;
float xyz[3]; // eye space
} finalvert_t;
#define FINALVERT_V0 0
#define FINALVERT_V1 2
#define FINALVERT_V2 4
#define FINALVERT_V3 6
#define FINALVERT_V4 8
#define FINALVERT_V5 12
#define FINALVERT_FLAGS 16
#define FINALVERT_X 20
#define FINALVERT_Y 24
#define FINALVERT_Z 28
#define FINALVERT_SIZE 32
#else
typedef struct finalvert_s {
int u, v, s, t;
int l;
int zi;
int flags;
float xyz[3]; // eye space
} finalvert_t;
#define FINALVERT_V0 0
#define FINALVERT_V1 4
#define FINALVERT_V2 8
#define FINALVERT_V3 12
#define FINALVERT_V4 16
#define FINALVERT_V5 20
#define FINALVERT_FLAGS 24
#define FINALVERT_X 28
#define FINALVERT_Y 32
#define FINALVERT_Z 36
#define FINALVERT_SIZE 40
#endif
typedef struct
{
void *pskin;
int pskindesc;
int skinwidth;
int skinheight;
dtriangle_t *ptriangles;
finalvert_t *pfinalverts;
int numtriangles;
int drawtype;
int seamfixupX16;
qboolean do_vis_thresh;
int vis_thresh;
} affinetridesc_t;
typedef struct
{
byte *surfdat; // destination for generated surface
int rowbytes; // destination logical width in bytes
msurface_t *surf; // description for surface to generate
fixed8_t lightadj[MAXLIGHTMAPS];
// adjust for lightmap levels for dynamic lighting
image_t *image;
int surfmip; // mipmapped ratio of surface texels / world pixels
int surfwidth; // in mipmapped texels
int surfheight; // in mipmapped texels
} drawsurf_t;
typedef struct {
int ambientlight;
int shadelight;
float *plightvec;
} alight_t;
// clipped bmodel edges
typedef struct bedge_s
{
mvertex_t *v[2];
struct bedge_s *pnext;
} bedge_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct clipplane_s
{
vec3_t normal;
float dist;
struct clipplane_s *next;
byte leftedge;
byte rightedge;
byte reserved[2];
} clipplane_t;
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
float mipscale;
image_t *image;
byte data[4]; // width*height elements
} surfcache_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct espan_s
{
int u, v, count;
struct espan_s *pnext;
} espan_t;
// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C)
typedef struct
{
int nump;
emitpoint_t *pverts;
byte *pixels; // image
int pixel_width; // image width
int pixel_height; // image height
vec3_t vup, vright, vpn; // in worldspace, for plane eq
float dist;
float s_offset, t_offset;
float viewer_position[3];
void (*drawspanlet)( void );
int stipple_parity;
} polydesc_t;
// FIXME: compress, make a union if that will help
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
typedef struct surf_s
{
struct surf_s *next; // active surface stack in r_edge.c
struct surf_s *prev; // used in r_edge.c for active surf stack
struct espan_s *spans; // pointer to linked list of spans to draw
int key; // sorting key (BSP order)
int last_u; // set during tracing
int spanstate; // 0 = not in span
// 1 = in span
// -1 = in inverted span (end before
// start)
int flags; // currentface flags
msurface_t *msurf;
entity_t *entity;
float nearzi; // nearest 1/z on surface, for mipmapping
qboolean insubmodel;
float d_ziorigin, d_zistepu, d_zistepv;
int pad[2]; // to 64 bytes
} surf_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct edge_s
{
fixed16_t u;
fixed16_t u_step;
struct edge_s *prev, *next;
unsigned short surfs[2];
struct edge_s *nextremove;
float nearzi;
medge_t *owner;
} edge_t;
/*
====================================================
VARS
====================================================
*/
extern int d_spanpixcount;
extern int r_framecount; // sequence # of current frame since Quake
// started
extern float r_aliasuvscale; // scale-up factor for screen u and v
// on Alias vertices passed to driver
extern qboolean r_dowarp;
extern affinetridesc_t r_affinetridesc;
extern vec3_t r_pright, r_pup, r_ppn;
void D_DrawSurfaces (void);
void R_DrawParticle( void );
void D_ViewChanged (void);
void D_WarpScreen (void);
void R_PolysetUpdateTables (void);
extern void *acolormap; // FIXME: should go away
//=======================================================================//
// callbacks to Quake
extern drawsurf_t r_drawsurf;
void R_DrawSurface (void);
extern int c_surf;
extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
extern float scale_for_mip;
extern qboolean d_roverwrapped;
extern surfcache_t *sc_rover;
extern surfcache_t *d_initial_rover;
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
extern fixed16_t sadjust, tadjust;
extern fixed16_t bbextents, bbextentt;
void D_DrawSpans16 (espan_t *pspans);
void D_DrawZSpans (espan_t *pspans);
void Turbulent8 (espan_t *pspan);
void NonTurbulent8 (espan_t *pspan); //PGM
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
extern int d_pix_min, d_pix_max, d_pix_shift;
extern pixel_t *d_viewbuffer;
extern short *d_pzbuffer;
extern unsigned int d_zrowbytes, d_zwidth;
extern short *zspantable[MAXHEIGHT];
extern int d_scantable[MAXHEIGHT];
extern int d_minmip;
extern float d_scalemip[3];
//===================================================================
extern int cachewidth;
extern pixel_t *cacheblock;
extern int r_screenwidth;
extern int r_drawnpolycount;
extern int sintable[1280];
extern int intsintable[1280];
extern int blanktable[1280]; // PGM
extern vec3_t vup, base_vup;
extern vec3_t vpn, base_vpn;
extern vec3_t vright, base_vright;
extern surf_t *surfaces, *surface_p, *surf_max;
// surfaces are generated in back to front order by the bsp, so if a surf
// pointer is greater than another one, it should be drawn in front
// surfaces[1] is the background, and is used as the active surface stack.
// surfaces[0] is a dummy, because index 0 is used to indicate no surface
// attached to an edge_t
//===================================================================
extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
extern vec3_t txformaxis[4]; // t axis transformed into viewspac
extern float xcenter, ycenter;
extern float xscale, yscale;
extern float xscaleinv, yscaleinv;
extern float xscaleshrink, yscaleshrink;
extern void TransformVector (vec3_t in, vec3_t out);
extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv);
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
//===========================================================================
extern cvar_t *sw_aliasstats;
extern cvar_t *sw_clearcolor;
extern cvar_t *sw_drawflat;
extern cvar_t *sw_draworder;
extern cvar_t *sw_maxedges;
extern cvar_t *sw_maxsurfs;
extern cvar_t *sw_mipcap;
extern cvar_t *sw_mipscale;
extern cvar_t *sw_mode;
extern cvar_t *sw_reportsurfout;
extern cvar_t *sw_reportedgeout;
extern cvar_t *sw_stipplealpha;
extern cvar_t *sw_surfcacheoverride;
extern cvar_t *sw_waterwarp;
extern cvar_t *r_fullbright;
extern cvar_t *r_lefthand;
extern cvar_t *r_drawentities;
extern cvar_t *r_drawworld;
extern cvar_t *r_dspeeds;
extern cvar_t *r_lerpmodels;
extern cvar_t *r_speeds;
extern cvar_t *r_lightlevel; //FIXME HACK
extern cvar_t *vid_fullscreen;
extern cvar_t *vid_gamma;
extern clipplane_t view_clipplanes[4];
extern int *pfrustum_indexes[4];
//=============================================================================
void R_RenderWorld (void);
//=============================================================================
extern mplane_t screenedge[4];
extern vec3_t r_origin;
extern entity_t r_worldentity;
extern model_t *currentmodel;
extern entity_t *currententity;
extern vec3_t modelorg;
extern vec3_t r_entorigin;
extern float verticalFieldOfView;
extern float xOrigin, yOrigin;
extern int r_visframecount;
extern msurface_t *r_alpha_surfaces;
//=============================================================================
void R_ClearPolyList (void);
void R_DrawPolyList (void);
//
// current entity info
//
extern qboolean insubmodel;
void R_DrawAlphaSurfaces( void );
void R_DrawSprite (void);
void R_DrawBeam( entity_t *e );
void R_RenderFace (msurface_t *fa, int clipflags);
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf);
void R_TransformPlane (mplane_t *p, float *normal, float *dist);
void R_TransformFrustum (void);
void R_DrawSurfaceBlock16 (void);
void R_DrawSurfaceBlock8 (void);
#if id386
void R_DrawSurfaceBlock8_mip0 (void);
void R_DrawSurfaceBlock8_mip1 (void);
void R_DrawSurfaceBlock8_mip2 (void);
void R_DrawSurfaceBlock8_mip3 (void);
#endif
void R_GenSkyTile (void *pdest);
void R_GenSkyTile16 (void *pdest);
void R_Surf8Patch (void);
void R_Surf16Patch (void);
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode);
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode);
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
surf_t *R_GetSurf (void);
void R_AliasDrawModel (void);
void R_BeginEdgeFrame (void);
void R_ScanEdges (void);
void D_DrawSurfaces (void);
void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist);
void R_StepActiveU (edge_t *pedge);
void R_RemoveEdges (edge_t *pedge);
void R_PushDlights (model_t *model);
extern void R_Surf8Start (void);
extern void R_Surf8End (void);
extern void R_Surf16Start (void);
extern void R_Surf16End (void);
extern void R_EdgeCodeStart (void);
extern void R_EdgeCodeEnd (void);
extern void R_RotateBmodel (void);
extern int c_faceclip;
extern int r_polycount;
extern int r_wholepolycount;
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
extern fixed16_t sadjust, tadjust;
extern fixed16_t bbextents, bbextentt;
extern mvertex_t *r_ptverts, *r_ptvertsmax;
extern float entity_rotation[3][3];
extern int r_currentkey;
extern int r_currentbkey;
void R_InitTurb (void);
void R_DrawParticles (void);
void R_SurfacePatch (void);
extern int r_amodels_drawn;
extern edge_t *auxedges;
extern int r_numallocatededges;
extern edge_t *r_edges, *edge_p, *edge_max;
extern edge_t *newedges[MAXHEIGHT];
extern edge_t *removeedges[MAXHEIGHT];
// FIXME: make stack vars when debugging done
extern edge_t edge_head;
extern edge_t edge_tail;
extern edge_t edge_aftertail;
extern int r_aliasblendcolor;
extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter;
extern int r_outofsurfaces;
extern int r_outofedges;
extern mvertex_t *r_pcurrentvertbase;
extern int r_maxvalidedgeoffset;
typedef struct
{
finalvert_t *a, *b, *c;
} aliastriangleparms_t;
extern aliastriangleparms_t aliastriangleparms;
void R_DrawTriangle( void );
//void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2);
extern float r_time1;
extern float da_time1, da_time2;
extern float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
extern float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
extern int r_frustum_indexes[4*6];
extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
extern qboolean r_surfsonstack;
extern mleaf_t *r_viewleaf;
extern int r_viewcluster, r_oldviewcluster;
extern int r_clipflags;
extern int r_dlightframecount;
extern qboolean r_fov_greater_than_90;
extern image_t *r_notexture_mip;
extern model_t *r_worldmodel;
void R_PrintAliasStats (void);
void R_PrintTimes (void);
void R_PrintDSpeeds (void);
void R_AnimateLight (void);
void R_LightPoint (vec3_t p, vec3_t color);
void R_SetupFrame (void);
void R_cshift_f (void);
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
void R_SplitEntityOnNode2 (mnode_t *node);
extern refdef_t r_newrefdef;
extern surfcache_t *sc_rover, *sc_base;
extern void *colormap;
//====================================================================
float R_DLightPoint (vec3_t p);
void R_NewMap (void);
void R_Register (void);
void R_UnRegister (void);
void Draw_InitLocal (void);
qboolean R_Init( void *hInstance, void *wndProc );
void R_Shutdown (void);
void R_InitCaches (void);
void D_FlushCaches (void);
void R_ScreenShot_f( void );
void R_BeginRegistration (char *map);
struct model_s *R_RegisterModel (char *name);
void R_EndRegistration (void);
void R_RenderFrame (refdef_t *fd);
struct image_s *Draw_FindPic (char *name);
void Draw_GetPicSize (int *w, int *h, char *name);
void Draw_Pic (int x, int y, char *name);
void Draw_StretchPic (int x, int y, int w, int h, char *name);
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
void Draw_Char (int x, int y, int c);
void Draw_TileClear (int x, int y, int w, int h, char *name);
void Draw_Fill (int x, int y, int w, int h, int c);
void Draw_FadeScreen (void);
void Draw_GetPalette (void);
void R_BeginFrame( float camera_separation );
void R_CinematicSetPalette( const unsigned char *palette );
extern unsigned d_8to24table[256]; // base
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length);
void Sys_SetFPCW (void);
void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height);
void R_InitImages (void);
void R_ShutdownImages (void);
image_t *R_FindImage (char *name, imagetype_t type);
void R_FreeUnusedImages (void);
void R_GammaCorrectAndSetPalette( const unsigned char *pal );
extern mtexinfo_t *sky_texinfo[6];
void R_InitSkyBox (void);
typedef struct swstate_s
{
qboolean fullscreen;
int prev_mode; // last valid SW mode
byte gammatable[256];
byte currentpalette[1024];
} swstate_t;
void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha );
extern swstate_t sw_state;
/*
====================================================================
IMPORTED FUNCTIONS
====================================================================
*/
extern refimport_t ri;
/*
====================================================================
IMPLEMENTATION FUNCTIONS
====================================================================
*/
void SWimp_BeginFrame( float camera_separation );
void SWimp_EndFrame (void);
int SWimp_Init( void *hInstance, void *wndProc );
void SWimp_SetPalette( const unsigned char *palette);
void SWimp_Shutdown( void );
rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen );
void SWimp_AppActivate( qboolean active );

1422
ref_soft/r_main.c Normal file

File diff suppressed because it is too large Load Diff

670
ref_soft/r_misc.c Normal file
View File

@ -0,0 +1,670 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_misc.c
#include "r_local.h"
#define NUM_MIPS 4
cvar_t *sw_mipcap;
cvar_t *sw_mipscale;
surfcache_t *d_initial_rover;
qboolean d_roverwrapped;
int d_minmip;
float d_scalemip[NUM_MIPS-1];
static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
extern int d_aflatcolor;
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
int d_pix_min, d_pix_max, d_pix_shift;
int d_scantable[MAXHEIGHT];
short *zspantable[MAXHEIGHT];
/*
================
D_Patch
================
*/
void D_Patch (void)
{
#if id386
extern void D_Aff8Patch( void );
static qboolean protectset8 = false;
extern void D_PolysetAff8Start( void );
if (!protectset8)
{
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
(int)D_Aff8Patch - (int)D_PolysetAff8Start);
Sys_MakeCodeWriteable ((long)R_Surf8Start,
(long)R_Surf8End - (long)R_Surf8Start);
protectset8 = true;
}
colormap = vid.colormap;
R_Surf8Patch ();
D_Aff8Patch();
#endif
}
/*
================
D_ViewChanged
================
*/
unsigned char *alias_colormap;
void D_ViewChanged (void)
{
int i;
scale_for_mip = xscale;
if (yscale > xscale)
scale_for_mip = yscale;
d_zrowbytes = vid.width * 2;
d_zwidth = vid.width;
d_pix_min = r_refdef.vrect.width / 320;
if (d_pix_min < 1)
d_pix_min = 1;
d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5);
d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5);
if (d_pix_max < 1)
d_pix_max = 1;
d_vrectx = r_refdef.vrect.x;
d_vrecty = r_refdef.vrect.y;
d_vrectright_particle = r_refdef.vrectright - d_pix_max;
d_vrectbottom_particle =
r_refdef.vrectbottom - d_pix_max;
for (i=0 ; i<vid.height; i++)
{
d_scantable[i] = i*r_screenwidth;
zspantable[i] = d_pzbuffer + i*d_zwidth;
}
/*
** clear Z-buffer and color-buffers if we're doing the gallery
*/
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
{
memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height,( int ) sw_clearcolor->value & 0xff );
}
alias_colormap = vid.colormap;
D_Patch ();
}
/*
=============
R_PrintTimes
=============
*/
void R_PrintTimes (void)
{
int r_time2;
int ms;
r_time2 = Sys_Milliseconds ();
ms = r_time2 - r_time1;
ri.Con_Printf (PRINT_ALL,"%5i ms %3i/%3i/%3i poly %3i surf\n",
ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf);
c_surf = 0;
}
/*
=============
R_PrintDSpeeds
=============
*/
void R_PrintDSpeeds (void)
{
int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time;
r_time2 = Sys_Milliseconds ();
da_time = (da_time2 - da_time1);
dp_time = (dp_time2 - dp_time1);
rw_time = (rw_time2 - rw_time1);
db_time = (db_time2 - db_time1);
se_time = (se_time2 - se_time1);
de_time = (de_time2 - de_time1);
ms = (r_time2 - r_time1);
ri.Con_Printf (PRINT_ALL,"%3i %2ip %2iw %2ib %2is %2ie %2ia\n",
ms, dp_time, rw_time, db_time, se_time, de_time, da_time);
}
/*
=============
R_PrintAliasStats
=============
*/
void R_PrintAliasStats (void)
{
ri.Con_Printf (PRINT_ALL,"%3i polygon model drawn\n", r_amodels_drawn);
}
/*
===================
R_TransformFrustum
===================
*/
void R_TransformFrustum (void)
{
int i;
vec3_t v, v2;
for (i=0 ; i<4 ; i++)
{
v[0] = screenedge[i].normal[2];
v[1] = -screenedge[i].normal[0];
v[2] = screenedge[i].normal[1];
v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
VectorCopy (v2, view_clipplanes[i].normal);
view_clipplanes[i].dist = DotProduct (modelorg, v2);
}
}
#if !(defined __linux__ && defined __i386__)
#if !id386
/*
================
TransformVector
================
*/
void TransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct(in,vright);
out[1] = DotProduct(in,vup);
out[2] = DotProduct(in,vpn);
}
#else
__declspec( naked ) void TransformVector( vec3_t vin, vec3_t vout )
{
__asm mov eax, dword ptr [esp+4]
__asm mov edx, dword ptr [esp+8]
__asm fld dword ptr [eax+0]
__asm fmul dword ptr [vright+0]
__asm fld dword ptr [eax+0]
__asm fmul dword ptr [vup+0]
__asm fld dword ptr [eax+0]
__asm fmul dword ptr [vpn+0]
__asm fld dword ptr [eax+4]
__asm fmul dword ptr [vright+4]
__asm fld dword ptr [eax+4]
__asm fmul dword ptr [vup+4]
__asm fld dword ptr [eax+4]
__asm fmul dword ptr [vpn+4]
__asm fxch st(2)
__asm faddp st(5), st(0)
__asm faddp st(3), st(0)
__asm faddp st(1), st(0)
__asm fld dword ptr [eax+8]
__asm fmul dword ptr [vright+8]
__asm fld dword ptr [eax+8]
__asm fmul dword ptr [vup+8]
__asm fld dword ptr [eax+8]
__asm fmul dword ptr [vpn+8]
__asm fxch st(2)
__asm faddp st(5), st(0)
__asm faddp st(3), st(0)
__asm faddp st(1), st(0)
__asm fstp dword ptr [edx+8]
__asm fstp dword ptr [edx+4]
__asm fstp dword ptr [edx+0]
__asm ret
}
#endif
#endif
/*
================
R_TransformPlane
================
*/
void R_TransformPlane (mplane_t *p, float *normal, float *dist)
{
float d;
d = DotProduct (r_origin, p->normal);
*dist = p->dist - d;
// TODO: when we have rotating entities, this will need to use the view matrix
TransformVector (p->normal, normal);
}
/*
===============
R_SetUpFrustumIndexes
===============
*/
void R_SetUpFrustumIndexes (void)
{
int i, j, *pindex;
pindex = r_frustum_indexes;
for (i=0 ; i<4 ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (view_clipplanes[i].normal[j] < 0)
{
pindex[j] = j;
pindex[j+3] = j+3;
}
else
{
pindex[j] = j+3;
pindex[j+3] = j;
}
}
// FIXME: do just once at start
pfrustum_indexes[i] = pindex;
pindex += 6;
}
}
/*
===============
R_ViewChanged
Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
===============
*/
void R_ViewChanged (vrect_t *vr)
{
int i;
r_refdef.vrect = *vr;
r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
r_refdef.fvrectx = (float)r_refdef.vrect.x;
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
r_refdef.fvrecty = (float)r_refdef.vrect.y;
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
r_refdef.fvrectright = (float)r_refdef.vrectright;
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
r_refdef.aliasvrect.height;
xOrigin = r_refdef.xOrigin;
yOrigin = r_refdef.yOrigin;
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
r_refdef.vrect.x - 0.5;
aliasxcenter = xcenter * r_aliasuvscale;
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
r_refdef.vrect.y - 0.5;
aliasycenter = ycenter * r_aliasuvscale;
xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
aliasxscale = xscale * r_aliasuvscale;
xscaleinv = 1.0 / xscale;
yscale = xscale;
aliasyscale = yscale * r_aliasuvscale;
yscaleinv = 1.0 / yscale;
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
yscaleshrink = xscaleshrink;
// left side clip
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;
// right side clip
screenedge[1].normal[0] =
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;
// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;
// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;
for (i=0 ; i<4 ; i++)
VectorNormalize (screenedge[i].normal);
D_ViewChanged ();
}
/*
===============
R_SetupFrame
===============
*/
void R_SetupFrame (void)
{
int i;
vrect_t vrect;
if (r_fullbright->modified)
{
r_fullbright->modified = false;
D_FlushCaches (); // so all lighting changes
}
r_framecount++;
// build the transformation matrix for the given view angles
VectorCopy (r_refdef.vieworg, modelorg);
VectorCopy (r_refdef.vieworg, r_origin);
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
// current viewleaf
if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
{
r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel);
r_viewcluster = r_viewleaf->cluster;
}
if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
r_dowarp = true;
else
r_dowarp = false;
if (r_dowarp)
{ // warp into off screen buffer
vrect.x = 0;
vrect.y = 0;
vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
d_viewbuffer = r_warpbuffer;
r_screenwidth = WARP_WIDTH;
}
else
{
vrect.x = r_newrefdef.x;
vrect.y = r_newrefdef.y;
vrect.width = r_newrefdef.width;
vrect.height = r_newrefdef.height;
d_viewbuffer = (void *)vid.buffer;
r_screenwidth = vid.rowbytes;
}
R_ViewChanged (&vrect);
// start off with just the four screen edge clip planes
R_TransformFrustum ();
R_SetUpFrustumIndexes ();
// save base values
VectorCopy (vpn, base_vpn);
VectorCopy (vright, base_vright);
VectorCopy (vup, base_vup);
// clear frame counts
c_faceclip = 0;
d_spanpixcount = 0;
r_polycount = 0;
r_drawnpolycount = 0;
r_wholepolycount = 0;
r_amodels_drawn = 0;
r_outofsurfaces = 0;
r_outofedges = 0;
// d_setup
d_roverwrapped = false;
d_initial_rover = sc_rover;
d_minmip = sw_mipcap->value;
if (d_minmip > 3)
d_minmip = 3;
else if (d_minmip < 0)
d_minmip = 0;
for (i=0 ; i<(NUM_MIPS-1) ; i++)
d_scalemip[i] = basemip[i] * sw_mipscale->value;
d_aflatcolor = 0;
}
#if !id386
/*
================
R_SurfacePatch
================
*/
void R_SurfacePatch (void)
{
// we only patch code on Intel
}
#endif // !id386
/*
==============================================================================
SCREEN SHOTS
==============================================================================
*/
/*
==============
WritePCXfile
==============
*/
void WritePCXfile (char *filename, byte *data, int width, int height,
int rowbytes, byte *palette)
{
int i, j, length;
pcx_t *pcx;
byte *pack;
FILE *f;
pcx = (pcx_t *)malloc (width*height*2+1000);
if (!pcx)
return;
pcx->manufacturer = 0x0a; // PCX id
pcx->version = 5; // 256 color
pcx->encoding = 1; // uncompressed
pcx->bits_per_pixel = 8; // 256 color
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = LittleShort((short)(width-1));
pcx->ymax = LittleShort((short)(height-1));
pcx->hres = LittleShort((short)width);
pcx->vres = LittleShort((short)height);
memset (pcx->palette,0,sizeof(pcx->palette));
pcx->color_planes = 1; // chunky image
pcx->bytes_per_line = LittleShort((short)width);
pcx->palette_type = LittleShort(2); // not a grey scale
memset (pcx->filler,0,sizeof(pcx->filler));
// pack the image
pack = &pcx->data;
for (i=0 ; i<height ; i++)
{
for (j=0 ; j<width ; j++)
{
if ( (*data & 0xc0) != 0xc0)
*pack++ = *data++;
else
{
*pack++ = 0xc1;
*pack++ = *data++;
}
}
data += rowbytes - width;
}
// write the palette
*pack++ = 0x0c; // palette ID byte
for (i=0 ; i<768 ; i++)
*pack++ = *palette++;
// write output file
length = pack - (byte *)pcx;
f = fopen (filename, "wb");
if (!f)
ri.Con_Printf (PRINT_ALL, "Failed to open to %s\n", filename);
else
{
fwrite ((void *)pcx, 1, length, f);
fclose (f);
}
free (pcx);
}
/*
==================
R_ScreenShot_f
==================
*/
void R_ScreenShot_f (void)
{
int i;
char pcxname[80];
char checkname[MAX_OSPATH];
FILE *f;
byte palette[768];
// create the scrnshots directory if it doesn't exist
Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
Sys_Mkdir (checkname);
//
// find a file name to save it to
//
strcpy(pcxname,"quake00.pcx");
for (i=0 ; i<=99 ; i++)
{
pcxname[5] = i/10 + '0';
pcxname[6] = i%10 + '0';
Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), pcxname);
f = fopen (checkname, "r");
if (!f)
break; // file doesn't exist
fclose (f);
}
if (i==100)
{
ri.Con_Printf (PRINT_ALL, "R_ScreenShot_f: Couldn't create a PCX");
return;
}
// turn the current 32 bit palette into a 24 bit palette
for (i=0 ; i<256 ; i++)
{
palette[i*3+0] = sw_state.currentpalette[i*4+0];
palette[i*3+1] = sw_state.currentpalette[i*4+1];
palette[i*3+2] = sw_state.currentpalette[i*4+2];
}
//
// save the pcx file
//
WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes,
palette);
ri.Con_Printf (PRINT_ALL, "Wrote %s\n", checkname);
}

1241
ref_soft/r_model.c Normal file

File diff suppressed because it is too large Load Diff

256
ref_soft/r_model.h Normal file
View File

@ -0,0 +1,256 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __MODEL__
#define __MODEL__
/*
d*_t structures are on-disk representations
m*_t structures are in-memory
*/
/*
==============================================================================
BRUSH MODELS
==============================================================================
*/
//
// in memory representation
//
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
} mvertex_t;
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
float dist;
byte type; // for texture axis selection and fast side tests
byte signbits; // signx + signy<<1 + signz<<1
byte pad[2];
} mplane_t;
// FIXME: differentiate from texinfo SURF_ flags
#define SURF_PLANEBACK 2
#define SURF_DRAWSKY 4 // sky brush face
#define SURF_DRAWTURB 0x10
#define SURF_DRAWBACKGROUND 0x40
#define SURF_DRAWSKYBOX 0x80 // sky box
#define SURF_FLOW 0x100 //PGM
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
unsigned int cachededgeoffset;
} medge_t;
typedef struct mtexinfo_s
{
float vecs[2][4];
float mipadjust;
image_t *image;
int flags;
int numframes;
struct mtexinfo_s *next; // animation chain
} mtexinfo_t;
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int dlightframe;
int dlightbits;
mplane_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
// surface generation data
struct surfcache_s *cachespots[MIPLEVELS];
short texturemins[2];
short extents[2];
mtexinfo_t *texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
byte *samples; // [numstyles*surfsize]
struct msurface_s *nextalphasurface;
} msurface_t;
#define CONTENTS_NODE -1
typedef struct mnode_s
{
// common with leaf
int contents; // CONTENTS_NODE, to differentiate from leafs
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// node specific
mplane_t *plane;
struct mnode_s *children[2];
unsigned short firstsurface;
unsigned short numsurfaces;
} mnode_t;
typedef struct mleaf_s
{
// common with node
int contents; // wil be something other than CONTENTS_NODE
int visframe; // node needs to be traversed if current
short minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
int cluster;
int area;
msurface_t **firstmarksurface;
int nummarksurfaces;
int key; // BSP sequence number for leaf's contents
} mleaf_t;
//===================================================================
//
// Whole model
//
typedef enum {mod_bad, mod_brush, mod_sprite, mod_alias } modtype_t;
typedef struct model_s
{
char name[MAX_QPATH];
int registration_sequence;
modtype_t type;
int numframes;
int flags;
//
// volume occupied by the model graphics
//
vec3_t mins, maxs;
//
// solid volume for clipping (sent from server)
//
qboolean clipbox;
vec3_t clipmins, clipmaxs;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
dmodel_t *submodels;
int numplanes;
mplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numvertexes;
mvertex_t *vertexes;
int numedges;
medge_t *edges;
int numnodes;
int firstnode;
mnode_t *nodes;
int numtexinfo;
mtexinfo_t *texinfo;
int numsurfaces;
msurface_t *surfaces;
int numsurfedges;
int *surfedges;
int nummarksurfaces;
msurface_t **marksurfaces;
dvis_t *vis;
byte *lightdata;
// for alias models and sprites
image_t *skins[MAX_MD2SKINS];
void *extradata;
int extradatasize;
} model_t;
//============================================================================
void Mod_Init (void);
void Mod_ClearAll (void);
model_t *Mod_ForName (char *name, qboolean crash);
void *Mod_Extradata (model_t *mod); // handles caching
void Mod_TouchModel (char *name);
mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
byte *Mod_ClusterPVS (int cluster, model_t *model);
void Mod_Modellist_f (void);
void Mod_FreeAll (void);
void Mod_Free (model_t *mod);
extern int registration_sequence;
#endif // __MODEL__

638
ref_soft/r_part.c Normal file
View File

@ -0,0 +1,638 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "r_local.h"
vec3_t r_pright, r_pup, r_ppn;
#define PARTICLE_33 0
#define PARTICLE_66 1
#define PARTICLE_OPAQUE 2
typedef struct
{
particle_t *particle;
int level;
int color;
} partparms_t;
static partparms_t partparms;
#if id386 && !defined __linux__
static unsigned s_prefetch_address;
/*
** BlendParticleXX
**
** Inputs:
** EAX = color
** EDI = pdest
**
** Scratch:
** EBX = scratch (dstcolor)
** EBP = scratch
**
** Outputs:
** none
*/
__declspec(naked) void BlendParticle33( void )
{
// return vid.alphamap[color + dstcolor*256];
__asm mov ebp, vid.alphamap
__asm xor ebx, ebx
__asm mov bl, byte ptr [edi]
__asm shl ebx, 8
__asm add ebp, ebx
__asm add ebp, eax
__asm mov al, byte ptr [ebp]
__asm mov byte ptr [edi], al
__asm ret
}
__declspec(naked) void BlendParticle66( void )
{
// return vid.alphamap[pcolor*256 + dstcolor];
__asm mov ebp, vid.alphamap
__asm xor ebx, ebx
__asm shl eax, 8
__asm mov bl, byte ptr [edi]
__asm add ebp, ebx
__asm add ebp, eax
__asm mov al, byte ptr [ebp]
__asm mov byte ptr [edi], al
__asm ret
}
__declspec(naked) void BlendParticle100( void )
{
__asm mov byte ptr [edi], al
__asm ret
}
/*
** R_DrawParticle (asm version)
**
** Since we use __declspec( naked ) we don't have a stack frame
** that we can use. Since I want to reserve EBP anyway, I tossed
** all the important variables into statics. This routine isn't
** meant to be re-entrant, so this shouldn't cause any problems
** other than a slightly higher global memory footprint.
**
*/
__declspec(naked) void R_DrawParticle( void )
{
static vec3_t local, transformed;
static float zi;
static int u, v, tmp;
static short izi;
static int ebpsave;
static byte (*blendfunc)(void);
/*
** must be memvars since x86 can't load constants
** directly. I guess I could use fld1, but that
** actually costs one more clock than fld [one]!
*/
static float particle_z_clip = PARTICLE_Z_CLIP;
static float one = 1.0F;
static float point_five = 0.5F;
static float eight_thousand_hex = 0x8000;
/*
** save trashed variables
*/
__asm mov ebpsave, ebp
__asm push esi
__asm push edi
/*
** transform the particle
*/
// VectorSubtract (pparticle->origin, r_origin, local);
__asm mov esi, partparms.particle
__asm fld dword ptr [esi+0] ; p_o.x
__asm fsub dword ptr [r_origin+0] ; p_o.x-r_o.x
__asm fld dword ptr [esi+4] ; p_o.y | p_o.x-r_o.x
__asm fsub dword ptr [r_origin+4] ; p_o.y-r_o.y | p_o.x-r_o.x
__asm fld dword ptr [esi+8] ; p_o.z | p_o.y-r_o.y | p_o.x-r_o.x
__asm fsub dword ptr [r_origin+8] ; p_o.z-r_o.z | p_o.y-r_o.y | p_o.x-r_o.x
__asm fxch st(2) ; p_o.x-r_o.x | p_o.y-r_o.y | p_o.z-r_o.z
__asm fstp dword ptr [local+0] ; p_o.y-r_o.y | p_o.z-r_o.z
__asm fstp dword ptr [local+4] ; p_o.z-r_o.z
__asm fstp dword ptr [local+8] ; (empty)
// transformed[0] = DotProduct(local, r_pright);
// transformed[1] = DotProduct(local, r_pup);
// transformed[2] = DotProduct(local, r_ppn);
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_pright+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_pright+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_pright+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm fstp dword ptr [transformed+0] ; (empty)
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_pup+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_pup+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_pup+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm fstp dword ptr [transformed+4] ; (empty)
__asm fld dword ptr [local+0] ; l.x
__asm fmul dword ptr [r_ppn+0] ; l.x*pr.x
__asm fld dword ptr [local+4] ; l.y | l.x*pr.x
__asm fmul dword ptr [r_ppn+4] ; l.y*pr.y | l.x*pr.x
__asm fld dword ptr [local+8] ; l.z | l.y*pr.y | l.x*pr.x
__asm fmul dword ptr [r_ppn+8] ; l.z*pr.z | l.y*pr.y | l.x*pr.x
__asm fxch st(2) ; l.x*pr.x | l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y | l.z*pr.z
__asm faddp st(1), st ; l.x*pr.x + l.y*pr.y + l.z*pr.z
__asm fstp dword ptr [transformed+8] ; (empty)
/*
** make sure that the transformed particle is not in front of
** the particle Z clip plane. We can do the comparison in
** integer space since we know the sign of one of the inputs
** and can figure out the sign of the other easily enough.
*/
// if (transformed[2] < PARTICLE_Z_CLIP)
// return;
__asm mov eax, dword ptr [transformed+8]
__asm and eax, eax
__asm js end
__asm cmp eax, particle_z_clip
__asm jl end
/*
** project the point by initiating the 1/z calc
*/
// zi = 1.0 / transformed[2];
__asm fld one
__asm fdiv dword ptr [transformed+8]
/*
** bind the blend function pointer to the appropriate blender
** while we're dividing
*/
//if ( level == PARTICLE_33 )
// blendparticle = BlendParticle33;
//else if ( level == PARTICLE_66 )
// blendparticle = BlendParticle66;
//else
// blendparticle = BlendParticle100;
__asm cmp partparms.level, PARTICLE_66
__asm je blendfunc_66
__asm jl blendfunc_33
__asm lea ebx, BlendParticle100
__asm jmp done_selecting_blend_func
blendfunc_33:
__asm lea ebx, BlendParticle33
__asm jmp done_selecting_blend_func
blendfunc_66:
__asm lea ebx, BlendParticle66
done_selecting_blend_func:
__asm mov blendfunc, ebx
// prefetch the next particle
__asm mov ebp, s_prefetch_address
__asm mov ebp, [ebp]
// finish the above divide
__asm fstp zi
// u = (int)(xcenter + zi * transformed[0] + 0.5);
// v = (int)(ycenter - zi * transformed[1] + 0.5);
__asm fld zi ; zi
__asm fmul dword ptr [transformed+0] ; zi * transformed[0]
__asm fld zi ; zi | zi * transformed[0]
__asm fmul dword ptr [transformed+4] ; zi * transformed[1] | zi * transformed[0]
__asm fxch st(1) ; zi * transformed[0] | zi * transformed[1]
__asm fadd xcenter ; xcenter + zi * transformed[0] | zi * transformed[1]
__asm fxch st(1) ; zi * transformed[1] | xcenter + zi * transformed[0]
__asm fld ycenter ; ycenter | zi * transformed[1] | xcenter + zi * transformed[0]
__asm fsubrp st(1), st(0) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0]
__asm fxch st(1) ; xcenter + zi * transformed[0] | ycenter + zi * transformed[1]
__asm fadd point_five ; xcenter + zi * transformed[0] + 0.5 | ycenter - zi * transformed[1]
__asm fxch st(1) ; ycenter - zi * transformed[1] | xcenter + zi * transformed[0] + 0.5
__asm fadd point_five ; ycenter - zi * transformed[1] + 0.5 | xcenter + zi * transformed[0] + 0.5
__asm fxch st(1) ; u | v
__asm fistp dword ptr [u] ; v
__asm fistp dword ptr [v] ; (empty)
/*
** clip out the particle
*/
// if ((v > d_vrectbottom_particle) ||
// (u > d_vrectright_particle) ||
// (v < d_vrecty) ||
// (u < d_vrectx))
// {
// return;
// }
__asm mov ebx, u
__asm mov ecx, v
__asm cmp ecx, d_vrectbottom_particle
__asm jg end
__asm cmp ecx, d_vrecty
__asm jl end
__asm cmp ebx, d_vrectright_particle
__asm jg end
__asm cmp ebx, d_vrectx
__asm jl end
/*
** compute addresses of zbuffer, framebuffer, and
** compute the Z-buffer reference value.
**
** EBX = U
** ECX = V
**
** Outputs:
** ESI = Z-buffer address
** EDI = framebuffer address
*/
// ESI = d_pzbuffer + (d_zwidth * v) + u;
__asm mov esi, d_pzbuffer ; esi = d_pzbuffer
__asm mov eax, d_zwidth ; eax = d_zwidth
__asm mul ecx ; eax = d_zwidth*v
__asm add eax, ebx ; eax = d_zwidth*v+u
__asm shl eax, 1 ; eax = 2*(d_zwidth*v+u)
__asm add esi, eax ; esi = ( short * ) ( d_pzbuffer + ( d_zwidth * v ) + u )
// initiate
// izi = (int)(zi * 0x8000);
__asm fld zi
__asm fmul eight_thousand_hex
// EDI = pdest = d_viewbuffer + d_scantable[v] + u;
__asm lea edi, [d_scantable+ecx*4]
__asm mov edi, [edi]
__asm add edi, d_viewbuffer
__asm add edi, ebx
// complete
// izi = (int)(zi * 0x8000);
__asm fistp tmp
__asm mov eax, tmp
__asm mov izi, ax
/*
** determine the screen area covered by the particle,
** which also means clamping to a min and max
*/
// pix = izi >> d_pix_shift;
__asm xor edx, edx
__asm mov dx, izi
__asm mov ecx, d_pix_shift
__asm shr dx, cl
// if (pix < d_pix_min)
// pix = d_pix_min;
__asm cmp edx, d_pix_min
__asm jge check_pix_max
__asm mov edx, d_pix_min
__asm jmp skip_pix_clamp
// else if (pix > d_pix_max)
// pix = d_pix_max;
check_pix_max:
__asm cmp edx, d_pix_max
__asm jle skip_pix_clamp
__asm mov edx, d_pix_max
skip_pix_clamp:
/*
** render the appropriate pixels
**
** ECX = count (used for inner loop)
** EDX = count (used for outer loop)
** ESI = zbuffer
** EDI = framebuffer
*/
__asm mov ecx, edx
__asm cmp ecx, 1
__asm ja over
over:
/*
** at this point:
**
** ECX = count
*/
__asm push ecx
__asm push edi
__asm push esi
top_of_pix_vert_loop:
top_of_pix_horiz_loop:
// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth)
// {
// for (i=0 ; i<pix ; i++)
// {
// if (pz[i] <= izi)
// {
// pdest[i] = blendparticle( color, pdest[i] );
// }
// }
// }
__asm xor eax, eax
__asm mov ax, word ptr [esi]
__asm cmp ax, izi
__asm jg end_of_horiz_loop
#if ENABLE_ZWRITES_FOR_PARTICLES
__asm mov bp, izi
__asm mov word ptr [esi], bp
#endif
__asm mov eax, partparms.color
__asm call [blendfunc]
__asm add edi, 1
__asm add esi, 2
end_of_horiz_loop:
__asm dec ecx
__asm jnz top_of_pix_horiz_loop
__asm pop esi
__asm pop edi
__asm mov ebp, d_zwidth
__asm shl ebp, 1
__asm add esi, ebp
__asm add edi, [r_screenwidth]
__asm pop ecx
__asm push ecx
__asm push edi
__asm push esi
__asm dec edx
__asm jnz top_of_pix_vert_loop
__asm pop ecx
__asm pop ecx
__asm pop ecx
end:
__asm pop edi
__asm pop esi
__asm mov ebp, ebpsave
__asm ret
}
#else
static byte BlendParticle33( int pcolor, int dstcolor )
{
return vid.alphamap[pcolor + dstcolor*256];
}
static byte BlendParticle66( int pcolor, int dstcolor )
{
return vid.alphamap[pcolor*256+dstcolor];
}
static byte BlendParticle100( int pcolor, int dstcolor )
{
dstcolor = dstcolor;
return pcolor;
}
/*
** R_DrawParticle
**
** Yes, this is amazingly slow, but it's the C reference
** implementation and should be both robust and vaguely
** understandable. The only time this path should be
** executed is if we're debugging on x86 or if we're
** recompiling and deploying on a non-x86 platform.
**
** To minimize error and improve readability I went the
** function pointer route. This exacts some overhead, but
** it pays off in clean and easy to understand code.
*/
void R_DrawParticle( void )
{
particle_t *pparticle = partparms.particle;
int level = partparms.level;
vec3_t local, transformed;
float zi;
byte *pdest;
short *pz;
int color = pparticle->color;
int i, izi, pix, count, u, v;
byte (*blendparticle)( int, int );
/*
** transform the particle
*/
VectorSubtract (pparticle->origin, r_origin, local);
transformed[0] = DotProduct(local, r_pright);
transformed[1] = DotProduct(local, r_pup);
transformed[2] = DotProduct(local, r_ppn);
if (transformed[2] < PARTICLE_Z_CLIP)
return;
/*
** bind the blend function pointer to the appropriate blender
*/
if ( level == PARTICLE_33 )
blendparticle = BlendParticle33;
else if ( level == PARTICLE_66 )
blendparticle = BlendParticle66;
else
blendparticle = BlendParticle100;
/*
** project the point
*/
// FIXME: preadjust xcenter and ycenter
zi = 1.0 / transformed[2];
u = (int)(xcenter + zi * transformed[0] + 0.5);
v = (int)(ycenter - zi * transformed[1] + 0.5);
if ((v > d_vrectbottom_particle) ||
(u > d_vrectright_particle) ||
(v < d_vrecty) ||
(u < d_vrectx))
{
return;
}
/*
** compute addresses of zbuffer, framebuffer, and
** compute the Z-buffer reference value.
*/
pz = d_pzbuffer + (d_zwidth * v) + u;
pdest = d_viewbuffer + d_scantable[v] + u;
izi = (int)(zi * 0x8000);
/*
** determine the screen area covered by the particle,
** which also means clamping to a min and max
*/
pix = izi >> d_pix_shift;
if (pix < d_pix_min)
pix = d_pix_min;
else if (pix > d_pix_max)
pix = d_pix_max;
/*
** render the appropriate pixels
*/
count = pix;
switch (level) {
case PARTICLE_33 :
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
{
//FIXME--do it in blocks of 8?
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = vid.alphamap[color + ((int)pdest[i]<<8)];
}
}
}
break;
case PARTICLE_66 :
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = vid.alphamap[(color<<8) + (int)pdest[i]];
}
}
}
break;
default: //100
for ( ; count ; count--, pz += d_zwidth, pdest += r_screenwidth)
{
for (i=0 ; i<pix ; i++)
{
if (pz[i] <= izi)
{
pz[i] = izi;
pdest[i] = color;
}
}
}
break;
}
}
#endif // !id386
/*
** R_DrawParticles
**
** Responsible for drawing all of the particles in the particle list
** throughout the world. Doesn't care if we're using the C path or
** if we're using the asm path, it simply assigns a function pointer
** and goes.
*/
void R_DrawParticles (void)
{
particle_t *p;
int i;
extern unsigned long fpu_sp24_cw, fpu_chop_cw;
VectorScale( vright, xscaleshrink, r_pright );
VectorScale( vup, yscaleshrink, r_pup );
VectorCopy( vpn, r_ppn );
#if id386 && !defined __linux__
__asm fldcw word ptr [fpu_sp24_cw]
#endif
for (p=r_newrefdef.particles, i=0 ; i<r_newrefdef.num_particles ; i++,p++)
{
if ( p->alpha > 0.66 )
partparms.level = PARTICLE_OPAQUE;
else if ( p->alpha > 0.33 )
partparms.level = PARTICLE_66;
else
partparms.level = PARTICLE_33;
partparms.particle = p;
partparms.color = p->color;
#if id386 && !defined __linux__
if ( i < r_newrefdef.num_particles-1 )
s_prefetch_address = ( unsigned int ) ( p + 1 );
else
s_prefetch_address = ( unsigned int ) r_newrefdef.particles;
#endif
R_DrawParticle();
}
#if id386 && !defined __linux__
__asm fldcw word ptr [fpu_chop_cw]
#endif
}

1244
ref_soft/r_poly.c Normal file

File diff suppressed because it is too large Load Diff