/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * Additional copyright for this file: * Copyright (C) 1999-2000 Revolution Software Ltd. * This code is based on source code created by Revolution Software, * used with permission. * * 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 3 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, see . * */ #include "engines/icb/global_objects.h" #include "engines/icb/actor.h" #include "engines/icb/gfx/psx_scrn.h" #include "engines/icb/gfx/psx_poly.h" #include "engines/icb/common/px_capri_maths.h" namespace ICB { // return 0 if on screen // return 1 if off screen int32 QuickActorCull(psxCamera *camera, VECTOR *pos, SVECTOR *orient) { MATRIX lw, ls; // Set the focal length in the GTE gte_SetGeomScreen(camera->focLen); // Now make a "true" local-world matrix i.e. without render correction RotMatrix_gte(orient, &lw); lw.t[0] = pos->vx; lw.t[1] = pos->vy; lw.t[2] = pos->vz; // Make the equivalent local-screen matrix // Should inline this makeLSmatrix(&camera->view, &lw, &ls); // Do a high level check to see if the actor and a very large bounding box are on the screen or not int16 xminLocal = -100; // -1m int16 yminLocal = 0; // on the ground int16 zminLocal = -100; // +1m int16 xmaxLocal = +100; // +1m int16 ymaxLocal = +200; // +2m high people int16 zmaxLocal = +100; // +1m SVECTOR bboxLocal[8]; bboxLocal[0].vx = xminLocal; bboxLocal[0].vy = yminLocal; bboxLocal[0].vz = zminLocal; bboxLocal[1].vx = xminLocal; bboxLocal[1].vy = yminLocal; bboxLocal[1].vz = zmaxLocal; bboxLocal[2].vx = xmaxLocal; bboxLocal[2].vy = yminLocal; bboxLocal[2].vz = zminLocal; bboxLocal[3].vx = xmaxLocal; bboxLocal[3].vy = yminLocal; bboxLocal[3].vz = zmaxLocal; bboxLocal[4].vx = xmaxLocal; bboxLocal[4].vy = ymaxLocal; bboxLocal[4].vz = zminLocal; bboxLocal[5].vx = xmaxLocal; bboxLocal[5].vy = ymaxLocal; bboxLocal[5].vz = zmaxLocal; bboxLocal[6].vx = xminLocal; bboxLocal[6].vy = ymaxLocal; bboxLocal[6].vz = zminLocal; bboxLocal[7].vx = xminLocal; bboxLocal[7].vy = ymaxLocal; bboxLocal[7].vz = zmaxLocal; SVECTOR *local = bboxLocal; SVECTOR bboxScrn[8]; SVECTOR *scrn = bboxScrn; int32 z0; int32 p, flag; int32 i; // Set the local-screen matrix in the GTE gte_SetRotMatrix(&ls); gte_SetTransMatrix(&ls); for (i = 0; i < 8; i++, local++, scrn++) { gte_RotTransPers(local, (int32 *)&(scrn->vx), &p, &flag, &z0); scrn->vz = (int16)z0; } // Find the minimum and maximum screen positions (plus z) scrn = bboxScrn; SVECTOR scrnMin, scrnMax; copyVector(&scrnMin, scrn); copyVector(&scrnMax, scrn); scrn++; for (i = 1; i < 8; i++, scrn++) { if (scrn->vx < scrnMin.vx) scrnMin.vx = scrn->vx; if (scrn->vy < scrnMin.vy) scrnMin.vy = scrn->vy; if (scrn->vz < scrnMin.vz) scrnMin.vz = scrn->vz; if (scrn->vx > scrnMax.vx) scrnMax.vx = scrn->vx; if (scrn->vy > scrnMax.vy) scrnMax.vy = scrn->vy; if (scrn->vz > scrnMax.vz) scrnMax.vz = scrn->vz; } // Reject the actor if the gross bounding box isn't on the screen yet if ((scrnMin.vx > (SCREEN_W / 2)) || // min x off right of the screen (scrnMin.vy > (SCREEN_H / 2)) || // min y off top of the screen (scrnMax.vx < (-SCREEN_W / 2)) || // max x off left of the screen (scrnMax.vy < (-SCREEN_H / 2)) || // max y off bottom of the screen (scrnMax.vz < g_actor_hither_plane) || // max z infront of the hither plane (scrnMin.vz > g_actor_far_clip_plane)) { // min z behind the max z plane return 1; } return 0; } } // End of namespace ICB