1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  *
26  */
27 
28 #include "engines/icb/common/px_common.h"
29 #include "engines/icb/p4_generic.h"
30 #include "engines/icb/debug.h"
31 #include "engines/icb/mission.h"
32 #include "engines/icb/text.h"
33 #include "engines/icb/direct_input.h"
34 #include "engines/icb/global_objects.h"
35 #include "engines/icb/global_switches.h"
36 #include "engines/icb/surface_manager.h"
37 #include "engines/icb/stage_draw.h"
38 #include "engines/icb/actor.h"
39 #include "engines/icb/actor_pc.h"
40 #include "engines/icb/res_man.h"
41 #include "engines/icb/common/px_capri_maths.h"
42 #include "engines/icb/gfx/psx_anims.h"
43 
44 namespace ICB {
45 
46 void PolyStageDraw(SDactor *actors, uint32 actorQty);
47 
Stage_draw_poly()48 void _game_session::Stage_draw_poly() {
49 	// The actors to draw
50 	SDactor actors[MAXIMUM_POTENTIAL_ON_SCREEN_ACTOR_QUANTITY];
51 
52 	// Get back which mega the actor could interact with
53 	int32 sel_id = GetSelectedMegaId();
54 
55 	// Fill in the actors that need drawing an update thier positions
56 	uint32 actorsToDraw = 0;
57 	int32 id;
58 	for (uint32 j = 0; j < number_of_voxel_ids; j++) {
59 		//		fetch the logic structure for the game object that has a voxel image to render
60 		id = (int32)voxel_id_list[j];
61 		_logic *log = logic_structs[id];
62 
63 		// Only clip by HITHER_PLANE, ActorDraw will clip image to film boundaries
64 		if (Object_visible_to_camera(id)) {
65 			g_mission->nActorsConsidered++;
66 
67 			bool8 result = TRUE8;
68 			PXvector filmPosition;
69 			PXWorldToFilm(log->mega->actor_xyz, set.GetCamera(), result, filmPosition);
70 
71 			if (filmPosition.z < -g_actor_hither_plane) {
72 				VECTOR v;
73 				v.vx = (int32)log->mega->actor_xyz.x;
74 				v.vy = (int32)log->mega->actor_xyz.y;
75 				v.vz = (int32)log->mega->actor_xyz.z;
76 
77 				SVECTOR orient;
78 				orient.vx = 0;
79 				orient.vy = 0;
80 				orient.vz = 0;
81 
82 				// Ignore characters who are off screen
83 				if (QuickActorCull((psxCamera *)&MSS.GetCamera(), &v, &orient) == 1)
84 					continue;
85 
86 				SDactor &thisActor = actors[actorsToDraw];
87 
88 				// do a high level anim file existence check!
89 				if (!log->voxel_info->IsAnimTable(log->cur_anim_type))
90 					Fatal_error("Illegal anim type [%s %s %s] for [%s]", master_anim_name_table[log->cur_anim_type].name, log->mega->chr_name,
91 					            log->mega->anim_set, log->GetName());
92 
93 				thisActor.anim_name =
94 				    log->voxel_info->anim_name[log->cur_anim_type]; // this should do the trick now that anim mega set.cpp sets names correct for polygons...
95 
96 				// setup act element
97 
98 				thisActor.frame = log->anim_pc;
99 
100 				psxActor &act = thisActor.psx_actor;
101 
102 				uint32 hash1 = NULL_HASH;
103 				uint32 hash2 = NULL_HASH;
104 
105 				PXanim_PSX *pAnim = (PXanim_PSX *)rs_anims->Res_open(log->voxel_info->info_name[log->cur_anim_type], hash1, log->voxel_info->base_path, hash2);
106 
107 				int32 f = log->anim_pc;
108 				if ((f < 0) || (f >= (int32)pAnim->frame_qty)) {
109 					f = (pAnim->frame_qty - 1);
110 				}
111 				PXmarker_PSX &marker = PXFrameEnOfAnim(f, pAnim)->markers[ORG_POS];
112 				float dx, dy, dz;
113 				marker.GetXYZ(&dx, &dy, &dz);
114 
115 				// Make the actors orientation matrix
116 				int32 pan;
117 				if (log->auto_panning == FALSE8)
118 					pan = (int32)((log->pan - log->pan_adjust) * 4096);
119 				else
120 					pan = (int32)((log->auto_display_pan - log->pan_adjust) * 4096);
121 
122 				act.rot.vx = 0;
123 				act.rot.vy = (int16)pan;
124 				act.rot.vz = 0;
125 
126 				// Because only one level in the hierarchy this is the lw matrix
127 				RotMatrix_gte(&act.rot, &act.lw);
128 				act.lw.t[0] = (int32)log->mega->actor_xyz.x;
129 				act.lw.t[1] = (int32)log->mega->actor_xyz.y;
130 				act.lw.t[2] = (int32)log->mega->actor_xyz.z;
131 
132 				// the bone local frame has the hip at 0,0,0
133 				// so put the hip at correct world height
134 				// uint32 dy = ( marker.pos.y == 0 ) ? 100 : marker.pos.y;
135 				// if ( log->cur_anim_type == __BEING_SHOT_DEAD ) dy = 0;
136 				act.lw.t[1] += (int32)dy;
137 
138 				// Set the actors true rotation & position values
139 				act.truePos.x = (int32)log->mega->actor_xyz.x;
140 				act.truePos.y = (int32)log->mega->actor_xyz.y;
141 				act.truePos.z = (int32)log->mega->actor_xyz.z;
142 
143 				act.truePos.y += (int32)dy;
144 
145 				act.trueRot.vx = 0;
146 
147 				if (log->auto_panning == FALSE8)
148 					act.trueRot.vy = (int16)(log->pan * 4096);
149 				else
150 					act.trueRot.vy = (int16)(log->auto_display_pan * 4096);
151 				act.trueRot.vz = 0;
152 
153 				//
154 				thisActor.log = log;
155 
156 				// if selected then set ambient to be ambientSelect otherwise it's ambient normal...
157 				uint8 r = 0;
158 				uint8 g = 0;
159 				uint8 b = 0;
160 
161 				if (id == sel_id) {
162 					GetSelectedMegaRGB(r, g, b);
163 				}
164 
165 				// mega RGB is 0-256
166 				thisActor.r = r;
167 				thisActor.g = g;
168 				thisActor.b = b;
169 
170 				//  must be reset
171 				log->pan_adjust = FLOAT_ZERO;
172 
173 				// And on to the next actor
174 				actorsToDraw++;
175 				g_mission->nActorsDrawn++;
176 			}
177 		}
178 	}
179 
180 	StageDrawPoly(actors, actorsToDraw);
181 }
182 
183 } // End of namespace ICB
184