1 ; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
\r
2 ; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
\r
3 ; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
\r
4 ; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
\r
5 ; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
\r
6 ; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
\r
7 ; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
\r
8 ; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
\r
9 ; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
\r
10 ; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
\r
18 include psmacros.inc
\r
23 assume cs:_TEXT, ds:_DATA
\r
25 _DATA segment dword public USE32 'DATA'
\r
27 ;table with address for each opcode
\r
28 opcode_table dd op_eof ;0 = eof
\r
29 dd op_defpoints ;1 = defpoints
\r
30 dd op_flatpoly ;2 = flat-shaded polygon
\r
31 dd op_tmappoly ;3 = texture-mapped polygon
\r
32 dd op_sortnorm ;4 = sort by normal
\r
33 dd op_rodbm ;5 = rod bitmap
\r
34 dd op_subcall ;6 = call a subobject
\r
35 dd op_defp_start ;7 = defpoints with start
\r
36 dd op_glow ;8 = glow value for next poly
\r
37 n_opcodes = ($-opcode_table)/4
\r
40 anim_angles dd ? ;pointer to angle data
\r
42 morph_points dd ? ;alternate points for morph
\r
44 ;light value for the next tmap
\r
45 glow_num dd -1 ;-1 means off
\r
46 glow_values dd ? ;ptr to array of values
\r
48 public _highest_texture_num
\r
49 _highest_texture_num dw 0
\r
51 zero_angles fixang 0,0,0 ;vms_angvec <0,0,0> ;for if no angles specified
\r
53 rod_top_p g3s_point <>
\r
54 rod_bot_p g3s_point <>
\r
56 public g3d_interp_outline,_g3d_interp_outline
\r
57 _g3d_interp_outline label dword
\r
58 g3d_interp_outline dd 0
\r
60 morph_pointlist dd ?,?,?
\r
62 morph_uvls fix 3 dup (?,?,?)
\r
64 ;the light for the current model
\r
67 ;ptr to array of points
\r
68 Interp_point_list dd ?
\r
70 MAX_POINTS_PER_POLY = 25
\r
72 point_list dd MAX_POINTS_PER_POLY dup (?)
\r
74 MAX_INTERP_COLORS = 100
\r
76 ;this is a table of mappings from RGB15 to palette colors
\r
77 interp_color_table dw MAX_INTERP_COLORS dup (?,?)
\r
79 n_interp_colors dd 0
\r
87 _TEXT segment dword public USE32 'CODE'
\r
89 ;get and jump to next opcode
\r
95 break_if ge,'Invalid opcode'
\r
97 mov ebx,opcode_table[ebx*4]
\r
101 ;get and call the next opcode
\r
107 break_if ge,'Invalid opcode'
\r
109 mov ebx,opcode_table[ebx*4]
\r
113 ;give the interpreter an array of points to use
\r
114 g3_set_interp_points:
\r
115 mov Interp_point_list,eax
\r
118 ;interpreter to draw polygon model
\r
119 ;takes esi=ptr to object, edi=ptr to array of bitmap pointers,
\r
120 ;eax=ptr to anim angles, edx=light value, ebx=ptr to array of glow values
\r
121 g3_draw_polygon_model:
\r
122 pushm eax,ebx,ecx,edx,esi,edi,ebp
\r
124 mov ebp,esi ;ebp = interp ptr
\r
126 mov bitmap_ptr,edi ;save ptr to bitmap array
\r
127 mov anim_angles,eax
\r
128 mov model_light,edx
\r
129 mov glow_values,ebx
\r
137 popm eax,ebx,ecx,edx,esi,edi,ebp
\r
140 ;handlers for opcodes
\r
142 ;end of a model or sub-rountine
\r
145 ;define a list of points
\r
146 op_defpoints: xor ecx,ecx
\r
147 mov cx,2[ebp] ;num points
\r
148 mov edi,Interp_point_list
\r
150 rotate_loop: call g3_rotate_point
\r
151 add edi,size g3s_point
\r
152 add esi,size vms_vector
\r
158 ;define a list of points, with starting point num specified
\r
159 op_defp_start: xor ecx,ecx
\r
161 mov ax,w 4[ebp] ;starting point num
\r
162 imulc eax,size g3s_point ;get ofs of point
\r
163 add eax,Interp_point_list
\r
165 mov cx,2[ebp] ;num points
\r
170 ;draw a flat-shaded polygon
\r
171 op_flatpoly: xor ecx,ecx
\r
172 mov cx,2[ebp] ;num verts
\r
173 lea esi,4[ebp] ;point
\r
174 lea edi,16[ebp] ;vector
\r
175 call g3_check_normal_facing
\r
176 jng flat_not_facing
\r
178 ;polygon is facing, so draw it
\r
180 ;here the glow parameter is used for the player's headlight
\r
181 test glow_num,-1 ;glow override?
\r
184 mov esi,glow_values
\r
185 mov eax,[esi+eax*4]
\r
187 cmp eax,-1 ;-1 means draw normal color
\r
188 jne not_normal_color
\r
189 ;use the color specified, run through darkening table
\r
191 mov eax,32 ;32 shades
\r
197 no_sat1: cmp eax,32
\r
200 no_sat2: mov bh,al ;get lighting table
\r
202 mov ax,28[ebp] ;get color index
\r
203 mov ax,interp_color_table[eax*4]
\r
205 mov al,gr_fade_table[ebx]
\r
206 jmp got_color_index
\r
207 not_normal_color: cmp eax,-2 ;-2 means use white
\r
210 jmp got_color_index
\r
211 not_white: cmp eax,-3 ;-3 means don't draw polygon
\r
216 mov ax,28[ebp] ;get color index
\r
217 mov ax,interp_color_table[eax*4]
\r
218 got_color_index: call gr_setcolor_ ;set it
\r
220 lea esi,30[ebp] ;point number list
\r
222 ;make list of point pointers
\r
225 cmp ecx,MAX_POINTS_PER_POLY
\r
226 break_if ge,'Too many points in interp poly'
\r
231 copy_loop: xor eax,eax
\r
232 mov ax,w [esi+ebx*2] ;get point number
\r
233 imulc eax,size g3s_point
\r
234 add eax,Interp_point_list
\r
235 mov [edi+ebx*4],eax
\r
243 mov cx,2[ebp] ;restore count
\r
246 test g3d_interp_outline,-1
\r
255 ;polygon is not facing (or we've plotted it). jump to next opcode
\r
256 flat_not_facing: and ecx,0fffffffeh
\r
257 inc ecx ;adjust for pad
\r
258 lea ebp,30[ebp+ecx*2]
\r
261 ;set the glow value for the next tmap
\r
262 op_glow: test glow_values,-1
\r
267 skip_glow: add ebp,4
\r
271 ;draw a texture map
\r
272 op_tmappoly: xor ecx,ecx
\r
273 mov cx,2[ebp] ;num verts
\r
274 lea esi,4[ebp] ;point
\r
275 lea edi,16[ebp] ;normal
\r
276 call g3_check_normal_facing
\r
277 jng tmap_not_facing
\r
279 ;polygon is facing, so draw it
\r
282 mov dx,28[ebp] ;get bitmap number
\r
284 mov edx,[eax+edx*4]
\r
286 lea esi,30[ebp] ;point number list
\r
290 lea ebx,30[ebp+eax*2] ;get uvl list
\r
292 ;calculate light from surface normal
\r
295 test glow_num,-1 ;glow override?
\r
297 ;special glow lighting, which doesn't care about surface normal
\r
299 mov esi,glow_values
\r
300 mov eax,[esi+eax*4]
\r
302 jmp got_light_value
\r
304 lea esi,View_matrix.fvec
\r
305 lea edi,16[ebp] ;normal
\r
306 call vm_vec_dotprod
\r
308 ;scale light by model light
\r
312 add eax,edx ;eax *= 3
\r
313 sar eax,2 ;eax *= 3/4
\r
314 add eax,f1_0/4 ;eax = 1/4 + eax * 3/4
\r
317 ;now poke light into l values
\r
318 got_light_value: pushm ecx,ebx
\r
319 l_loop: mov 8[ebx],eax
\r
327 ;make list of point pointers
\r
330 cmp ecx,MAX_POINTS_PER_POLY
\r
331 break_if ge,'Too many points in interp poly'
\r
337 copy_loop2: xor eax,eax
\r
338 mov ax,w [esi+ebx*2] ;get point number
\r
339 imulc eax,size g3s_point
\r
340 add eax,Interp_point_list
\r
341 mov [edi+ebx*4],eax
\r
350 mov cx,2[ebp] ;restore count
\r
353 test g3d_interp_outline,-1
\r
362 ;polygon is not facing (or we've plotted it). jump to next opcode
\r
363 tmap_not_facing: mov ebx,ecx
\r
365 inc ebx ;adjust for pad
\r
366 lea ebp,30[ebp+ebx*2]
\r
371 sal ecx,2 ;ecx=ecx*12
\r
372 add ebp,ecx ;point past uvls
\r
376 ;sort based on surface normal
\r
377 op_sortnorm: lea esi,16[ebp] ;point
\r
378 lea edi,4[ebp] ;vector
\r
379 call g3_check_normal_facing
\r
380 jng sortnorm_not_facing
\r
382 ;is facing. draw back then front
\r
386 mov ax,30[ebp] ;get back offset
\r
389 mov ebp,[esp] ;get ebp
\r
391 mov ax,28[ebp] ;get front offset
\r
399 ;is not facing. draw front then back
\r
401 sortnorm_not_facing:
\r
404 mov ax,28[ebp] ;get back offset
\r
407 mov ebp,[esp] ;get ebp
\r
409 mov ax,30[ebp] ;get front offset
\r
417 ;draw a rod bitmap
\r
418 op_rodbm: lea esi,20[ebp] ;bot point
\r
420 call g3_rotate_point
\r
422 lea esi,4[ebp] ;top point
\r
424 call g3_rotate_point
\r
426 lea esi,rod_bot_p ;esi=bot, edi=top
\r
427 mov eax,16[ebp] ;bot width
\r
428 mov edx,32[ebp] ;top width
\r
431 mov bx,2[ebp] ;get bitmap number
\r
433 mov ebx,[ecx+ebx*4]
\r
435 call g3_draw_rod_tmap
\r
442 op_subcall: xor eax,eax
\r
443 mov ax,2[ebp] ;get object number
\r
446 mov edi,anim_angles
\r
448 jnz angles_not_null
\r
449 ;angles not specified. Use zero angles
\r
450 lea edi,zero_angles
\r
453 imulc eax,size vms_angvec
\r
458 lea esi,4[ebp] ;get position
\r
459 call g3_start_instance_angles
\r
464 add ebp,eax ;offset of subobject
\r
465 call_next ;draw the subobject
\r
468 call g3_done_instance
\r
473 ;takes ax, returns ax
\r
474 find_color_index: push ebx
\r
476 ;first, see if color already in table
\r
478 xor ebx,ebx ;counter
\r
479 look_loop: cmp ebx,n_interp_colors
\r
481 cmp ax,interp_color_table+2[ebx*4]
\r
486 must_add_color: mov interp_color_table+2[ebx*4],ax ;save rgb15
\r
487 call gr_find_closest_color_15bpp_
\r
488 mov interp_color_table[ebx*4],ax ;save pal entry
\r
489 inc n_interp_colors
\r
491 found_color: mov eax,ebx ;return index
\r
495 ;this remaps the 15bpp colors for the models into a new palette. It should
\r
496 ;be called whenever the palette changes
\r
497 g3_remap_interp_colors:
\r
501 remap_loop: cmp ebx,n_interp_colors
\r
505 mov ax,interp_color_table+2[ebx*4] ;get rgb15
\r
506 call gr_find_closest_color_15bpp_
\r
507 mov interp_color_table[ebx*4],ax ;store pal entry
\r
512 done_remap: popm eax,ebx
\r
516 ;maps the colors back to RGB15
\r
517 g3_uninit_polygon_model:
\r
520 ;initialize a polygon object
\r
521 ;translate colors, scale UV values
\r
522 ;takes esi=ptr to model
\r
523 g3_init_polygon_model:
\r
524 mov _highest_texture_num,-1
\r
526 pushm eax,ebx,ecx,edx,esi,edi
\r
528 popm eax,ebx,ecx,edx,esi,edi
\r
534 init_loop: mov ax,[esi] ;get opcode
\r
541 cmp ax,1 ;defpoints
\r
544 mov ax,2[esi] ;get count
\r
547 lea esi,4[esi+eax*4]
\r
556 break_if l,'face must have 3 or more points'
\r
558 ; The following 3 lines replace the above
\r
560 mov ax,28[esi] ;get color
\r
561 test uninit_flag,-1
\r
564 mov ax,interp_color_table+2[eax*4]
\r
567 call find_color_index
\r
568 cont1: mov 28[esi],ax ;store new color
\r
571 mov cx,2[esi] ;get nverts
\r
573 inc ecx ;adjust for pad
\r
574 lea esi,30[esi+ecx*2]
\r
583 break_if l,'face must have 3 or more points'
\r
585 mov ax,28[esi] ;get bitmap number
\r
586 cmp ax,_highest_texture_num
\r
588 mov _highest_texture_num,ax
\r
589 not_new: xor ecx,ecx
\r
590 mov cx,2[esi] ;get nverts
\r
593 inc ebx ;adjust for pad
\r
594 lea esi,30[esi+ebx*2] ;point at uvls
\r
596 imul ecx,12 ;size of uvls
\r
597 add esi,ecx ;skip them
\r
600 ;;@@init_uv_loop: mov eax,[esi] ;get u
\r
601 ;;@@ imul eax,64 ;times bitmap w
\r
603 ;;@@ mov eax,4[esi] ;get v
\r
604 ;;@@ imul eax,64 ;times bitmap h
\r
605 ;;@@ mov 4[esi],eax
\r
606 ;;@@ add esi,12 ;point at next
\r
608 ;;@@ jnz init_uv_loop
\r
618 mov ax,28[esi] ;get front offset
\r
623 mov ax,30[esi] ;get front offset
\r
644 mov ax,16[esi] ;get subobj offset
\r
652 cmp ax,7 ;defpoints
\r
653 jne not_defpoints_st
\r
655 mov ax,2[esi] ;get count
\r
658 lea esi,8[esi+eax*4]
\r
667 debug_brk "Invalid opcode"
\r
672 ;takes ecx=count, esi=ptr to point list
\r
673 draw_outline: pushm eax,ebx,ecx,edx,esi,edi
\r
675 ;NO_INVERSE_TABLE xor eax,eax
\r
676 ;NO_INVERSE_TABLE mov al,gr_inverse_table[7fffh] ;white
\r
677 mov eax, 255 ; bright white
\r
683 mov ax,[ebx] ;get first point
\r
686 outline_loop: xor esi,esi
\r
694 imul esi,size g3s_point
\r
695 add esi,Interp_point_list
\r
696 imul edi,size g3s_point
\r
697 add edi,Interp_point_list
\r
705 done_loop: pop edi ;get first point back
\r
707 imul esi,size g3s_point
\r
708 add esi,Interp_point_list
\r
709 imul edi,size g3s_point
\r
710 add edi,Interp_point_list
\r
714 popm eax,ebx,ecx,edx,esi,edi
\r
717 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
719 ;Special code to draw morphing objects
\r
721 ;define a list of points
\r
722 morph_defpoints: xor ecx,ecx
\r
723 mov cx,2[ebp] ;num points
\r
724 mov edi,Interp_point_list
\r
726 morph_rotate_list: lea eax,[ecx*2+ecx] ;eax=npoint * 3
\r
727 lea esi,[esi+eax*4] ;point past points
\r
729 mov esi,morph_points ;get alternate points
\r
730 morph_rotate_loop: call g3_rotate_point
\r
731 add edi,size g3s_point
\r
732 add esi,size vms_vector
\r
734 jnz morph_rotate_loop
\r
735 pop esi ;restore pointer
\r
739 ;define a list of points, with starting point num specified
\r
740 morph_defp_start: xor ecx,ecx
\r
742 mov ax,w 4[ebp] ;starting point num
\r
743 imulc eax,size g3s_point ;get ofs of point
\r
744 add eax,Interp_point_list
\r
746 mov cx,2[ebp] ;num points
\r
748 jmp morph_rotate_list
\r
750 ;draw a flat-shaded polygon
\r
751 morph_flatpoly: xor ecx,ecx
\r
752 mov cx,2[ebp] ;num verts
\r
753 lea esi,4[ebp] ;point
\r
754 lea edi,16[ebp] ;vector
\r
758 mov ax,28[ebp] ;get color
\r
759 mov ax,interp_color_table[eax*4]
\r
760 call gr_setcolor_ ;set it
\r
763 lea esi,30[ebp] ;point number list
\r
767 imulc eax,size g3s_point
\r
768 add eax,Interp_point_list
\r
769 mov morph_pointlist,eax
\r
772 imulc eax,size g3s_point
\r
773 add eax,Interp_point_list
\r
774 mov morph_pointlist+4,eax
\r
777 imulc eax,size g3s_point
\r
778 add eax,Interp_point_list
\r
779 mov morph_pointlist+8,eax
\r
781 cmp ecx,3 ;3 points is good!
\r
783 sub ecx,2 ;tri count
\r
785 flat_tri_loop: xor edi,edi ;no normal, must compute
\r
787 mov ecx,3 ;always draw triangle
\r
788 lea esi,morph_pointlist
\r
789 call g3_check_and_draw_poly
\r
792 mov eax,morph_pointlist+8
\r
793 mov morph_pointlist+4,eax
\r
796 imulc eax,size g3s_point
\r
797 add eax,Interp_point_list
\r
798 mov morph_pointlist+8,eax
\r
805 lea esi,morph_pointlist
\r
806 xor edi,edi ;no normal, must compute
\r
807 call g3_check_and_draw_poly
\r
809 flat_done_draw: xor ecx,ecx
\r
810 mov cx,2[ebp] ;restore count
\r
813 inc ecx ;adjust for pad
\r
814 lea ebp,30[ebp+ecx*2]
\r
817 ;draw a texture map
\r
818 morph_tmappoly: xor ecx,ecx
\r
819 mov cx,2[ebp] ;num verts
\r
820 lea esi,4[ebp] ;point
\r
821 lea edi,16[ebp] ;normal
\r
825 mov dx,28[ebp] ;get bitmap number
\r
827 mov edx,[eax+edx*4]
\r
829 lea esi,30[ebp] ;point number list
\r
833 lea ebx,30[ebp+eax*2] ;get uvl list
\r
834 ;calculate light from surface normal
\r
836 lea esi,View_matrix.fvec
\r
837 lea edi,16[ebp] ;normal
\r
838 call vm_vec_dotprod
\r
840 ;scale light by model light
\r
844 add eax,edx ;eax *= 3
\r
845 sar eax,2 ;eax *= 3/4
\r
846 add eax,f1_0/4 ;eax = 1/4 + eax * 3/4
\r
856 ;now eax=plane light value
\r
858 mov morph_uvls+8,eax
\r
859 mov morph_uvls+20,eax
\r
860 mov morph_uvls+32,eax
\r
864 imulc eax,size g3s_point
\r
865 add eax,Interp_point_list
\r
866 mov morph_pointlist,eax
\r
869 imulc eax,size g3s_point
\r
870 add eax,Interp_point_list
\r
871 mov morph_pointlist+4,eax
\r
874 imulc eax,size g3s_point
\r
875 add eax,Interp_point_list
\r
876 mov morph_pointlist+8,eax
\r
878 cmp ecx,3 ;3 points is good!
\r
879 jl tmap_done_draw ;something is bad, abort
\r
881 sub ecx,2 ;tri count
\r
888 mov morph_uvls+4,edx
\r
891 mov morph_uvls+12,edx
\r
893 mov morph_uvls+16,edx
\r
896 mov morph_uvls+24,edx
\r
898 mov morph_uvls+28,edx
\r
905 tmap_tri_loop: xor edi,edi ;no normal, must compute
\r
906 pushm ebx,edx,ecx,esi
\r
907 mov ecx,3 ;always draw triangle
\r
908 lea esi,morph_pointlist
\r
910 call g3_check_and_draw_tmap
\r
911 popm ebx,edx,ecx,esi
\r
913 mov eax,morph_pointlist+8
\r
914 mov morph_pointlist+4,eax
\r
917 imulc eax,size g3s_point
\r
918 add eax,Interp_point_list
\r
919 mov morph_pointlist+8,eax
\r
922 mov edx,morph_uvls+24
\r
923 mov morph_uvls+12,edx
\r
924 mov edx,morph_uvls+28
\r
925 mov morph_uvls+16,edx
\r
928 mov morph_uvls+24,edx
\r
930 mov morph_uvls+28,edx
\r
939 ;poke in light values
\r
941 tmap_l_loop: mov 8[ebx],eax
\r
947 lea esi,morph_pointlist
\r
949 xor edi,edi ;no normal
\r
950 call g3_check_and_draw_tmap
\r
952 tmap_done_draw: xor ecx,ecx
\r
953 mov cx,2[ebp] ;restore count
\r
955 ;jump to next opcode
\r
958 inc ebx ;adjust for pad
\r
959 lea ebp,30[ebp+ebx*2]
\r
964 sal ecx,2 ;ecx=ecx*12
\r
965 add ebp,ecx ;point past uvls
\r
970 ;interpreter to draw polygon model
\r
971 ;takes esi=ptr to object, edi=ptr to array of bitmap pointers,
\r
972 ;eax=ptr to anim angles, ebx=alternate points, edx=light value
\r
974 g3_draw_morphing_model:
\r
975 pushm eax,ebx,ecx,edx,esi,edi,ebp
\r
977 mov bitmap_ptr,edi ;save ptr to bitmap array
\r
978 mov anim_angles,eax
\r
979 mov morph_points,ebx
\r
980 mov model_light,edx
\r
982 mov ebp,esi ;ebp = interp ptr
\r
984 ;set alternate opcode pointers
\r
986 push opcode_table[1*4] ;defpoints
\r
987 push opcode_table[2*4] ;flatpoly
\r
988 push opcode_table[3*4] ;tmappoly
\r
989 push opcode_table[7*4] ;defp_start
\r
991 mov opcode_table[1*4],offset morph_defpoints
\r
992 mov opcode_table[2*4],offset morph_flatpoly
\r
993 mov opcode_table[3*4],offset morph_tmappoly
\r
994 mov opcode_table[7*4],offset morph_defp_start
\r
998 pop opcode_table[7*4] ;defp_start
\r
999 pop opcode_table[3*4] ;tmappoly
\r
1000 pop opcode_table[2*4] ;flatpoly
\r
1001 pop opcode_table[1*4] ;defpoints
\r
1003 popm eax,ebx,ecx,edx,esi,edi,ebp
\r