mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-10 03:40:25 +00:00
2c9ea9ea99
texture mapping with light shading is not implemented in TynyGL (yet), to enable shading without texture mapping look into beginning of TinyGL driver
262 lines
7.2 KiB
C++
262 lines
7.2 KiB
C++
// Residual - Virtual machine to run LucasArts' 3D adventure games
|
|
// Copyright (C) 2003-2005 The ScummVM-Residual Team (www.scummvm.org)
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#include "stdafx.h"
|
|
#include "scene.h"
|
|
#include "textsplit.h"
|
|
#include "resource.h"
|
|
#include "debug.h"
|
|
#include "bitmap.h"
|
|
#include "colormap.h"
|
|
#include "vector3d.h"
|
|
#include "driver.h"
|
|
|
|
#include "imuse/imuse.h"
|
|
|
|
#include <SDL.h>
|
|
#include <cmath>
|
|
|
|
Scene::Scene(const char *name, const char *buf, int len) :
|
|
_name(name) {
|
|
TextSplitter ts(buf, len);
|
|
char tempBuf[256];
|
|
|
|
ts.expectString("section: colormaps");
|
|
ts.scanString(" numcolormaps %d", 1, &_numCmaps);
|
|
_cmaps = new ResPtr<CMap>[_numCmaps];
|
|
char cmap_name[256];
|
|
for (int i = 0; i < _numCmaps; i++) {
|
|
ts.scanString(" colormap %256s", 1, cmap_name);
|
|
_cmaps[i] = g_resourceloader->loadColormap(cmap_name);
|
|
}
|
|
|
|
ts.expectString("section: setups");
|
|
ts.scanString(" numsetups %d", 1, &_numSetups);
|
|
_setups = new Setup[_numSetups];
|
|
for (int i = 0; i < _numSetups; i++)
|
|
_setups[i].load(ts);
|
|
_currSetup = _setups;
|
|
|
|
_numSectors = -1;
|
|
_numLights = -1;
|
|
_lights = NULL;
|
|
_sectors = NULL;
|
|
|
|
_minVolume = 0;
|
|
_maxVolume = 0;
|
|
|
|
// Lights are optional
|
|
if (ts.eof())
|
|
return;
|
|
|
|
ts.expectString("section: lights");
|
|
ts.scanString(" numlights %d", 1, &_numLights);
|
|
_lights = new Light[_numLights];
|
|
for (int i = 0; i < _numLights; i++)
|
|
_lights[i].load(ts);
|
|
|
|
// Calculate the number of sectors
|
|
ts.expectString("section: sectors");
|
|
if (ts.eof()) // Sectors are optional, but section: doesn't seem to be
|
|
return;
|
|
|
|
// Sector NAMES can be null, but ts doesn't seem flexible enough to allow this
|
|
if (strlen(ts.currentLine()) > strlen(" sector"))
|
|
ts.scanString(" sector %256s", 1, tempBuf);
|
|
else {
|
|
ts.nextLine();
|
|
strcpy(tempBuf, "");
|
|
}
|
|
|
|
ts.scanString(" id %d", 1, &_numSectors);
|
|
_numSectors++;
|
|
_sectors = new Sector[_numSectors];
|
|
// FIXME: This would be nicer if we could rewind the textsplitter
|
|
// stream
|
|
_sectors[0].load0(ts, tempBuf, _numSectors);
|
|
for (int i = 1; i < _numSectors; i++)
|
|
_sectors[i].load(ts);
|
|
}
|
|
|
|
Scene::~Scene() {
|
|
delete [] _cmaps;
|
|
delete [] _setups;
|
|
if (_lights)
|
|
delete [] _lights;
|
|
if (_sectors)
|
|
delete [] _sectors;
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); i++)
|
|
delete (*i);
|
|
}
|
|
|
|
void Scene::Setup::load(TextSplitter &ts) {
|
|
char buf[256];
|
|
|
|
ts.scanString(" setup %256s", 1, buf);
|
|
_name = buf;
|
|
|
|
ts.scanString(" background %256s", 1, buf);
|
|
_bkgndBm = g_resourceloader->loadBitmap(buf);
|
|
|
|
// ZBuffer is optional
|
|
if (!ts.checkString("zbuffer")) {
|
|
_bkgndZBm = NULL;
|
|
} else {
|
|
ts.scanString(" zbuffer %256s", 1, buf);
|
|
_bkgndZBm = g_resourceloader->loadBitmap(buf);
|
|
}
|
|
|
|
ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z());
|
|
ts.scanString(" interest %f %f %f", 3, &_interest.x(), &_interest.y(), &_interest.z());
|
|
ts.scanString(" roll %f", 1, &_roll);
|
|
ts.scanString(" fov %f", 1, &_fov);
|
|
ts.scanString(" nclip %f", 1, &_nclip);
|
|
ts.scanString(" fclip %f", 1, &_fclip);
|
|
}
|
|
|
|
void Scene::Light::load(TextSplitter &ts) {
|
|
char buf[256];
|
|
|
|
// Light names can be null, but ts doesn't seem flexible enough to allow this
|
|
if (strlen(ts.currentLine()) > strlen(" light"))
|
|
ts.scanString(" light %256s", 1, buf);
|
|
else {
|
|
ts.nextLine();
|
|
strcpy(buf, "");
|
|
}
|
|
_name = buf;
|
|
|
|
ts.scanString(" type %256s", 1, buf);
|
|
_type = buf;
|
|
|
|
ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z());
|
|
ts.scanString(" direction %f %f %f", 3, &_dir.x(), &_dir.y(), &_dir.z());
|
|
ts.scanString(" intensity %f", 1, &_intensity);
|
|
ts.scanString(" umbraangle %f", 1, &_umbraangle);
|
|
ts.scanString(" penumbraangle %f", 1, &_penumbraangle);
|
|
|
|
int r, g, b;
|
|
ts.scanString(" color %d %d %d", 3, &r, &g, &b);
|
|
_color.red() = r;
|
|
_color.green() = g;
|
|
_color.blue() = b;
|
|
}
|
|
|
|
void Scene::Setup::setupCamera() const {
|
|
// Ignore nclip_ and fclip_ for now. This fixes:
|
|
// (a) Nothing was being displayed in the Land of the Living
|
|
// diner because lr.set set nclip to 0.
|
|
// (b) The zbuffers for setups with different nclip or
|
|
// fclip values. If it turns out that the clipping planes
|
|
// are important at some point, we'll need to modify the
|
|
// zbuffer transformation in bitmap.cpp to take nclip_ and
|
|
// fclip_ into account.
|
|
g_driver->setupCamera(_fov, 0.01f, 3276.8f, _roll);
|
|
g_driver->positionCamera(_pos, _interest);
|
|
}
|
|
|
|
void Scene::setupLights() {
|
|
if (!_enableLights) {
|
|
g_driver->disableLights();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < _numLights; i++) {
|
|
assert(i < TGL_MAX_LIGHTS);
|
|
g_driver->setupLight(&_lights[i], i);
|
|
}
|
|
}
|
|
|
|
void Scene::setSetup(int num) {
|
|
_currSetup = _setups + num;
|
|
}
|
|
|
|
void Scene::drawBitmaps(ObjectState::Position stage) {
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); i++) {
|
|
if ((*i)->pos() == stage && _currSetup == _setups + (*i)->setupID())
|
|
(*i)->draw();
|
|
}
|
|
}
|
|
|
|
Sector *Scene::findPointSector(Vector3d p, int flags) {
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
Sector *sector = _sectors + i;
|
|
if ((sector->type() & flags) && sector->visible() &&
|
|
sector->isPointInSector(p))
|
|
return sector;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void Scene::findClosestSector(Vector3d p, Sector **sect, Vector3d *closestPt) {
|
|
Sector *resultSect = NULL;
|
|
Vector3d resultPt = p;
|
|
float minDist;
|
|
|
|
for (int i = 0; i < _numSectors; i++) {
|
|
Sector *sector = _sectors + i;
|
|
if ((sector->type() & 0x1000) == 0 || !sector->visible())
|
|
continue;
|
|
Vector3d closestPt = sector->closestPoint(p);
|
|
float thisDist = (closestPt - p).magnitude();
|
|
if (resultSect == NULL || thisDist < minDist) {
|
|
resultSect = sector;
|
|
resultPt = closestPt;
|
|
minDist = thisDist;
|
|
}
|
|
}
|
|
|
|
if (sect != NULL)
|
|
*sect = resultSect;
|
|
|
|
if (closestPt != NULL)
|
|
*closestPt = resultPt;
|
|
}
|
|
|
|
ObjectState *Scene::findState(const char *filename) {
|
|
for (StateList::iterator i = _states.begin(); i != _states.end(); i++) {
|
|
if (strcmp((*i)->bitmapFilename(), filename) == 0)
|
|
return *i;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void Scene::setSoundPosition(const char *soundName, Vector3d pos) {
|
|
Vector3d cameraPos = _currSetup->_pos;
|
|
Vector3d vector, vector2;
|
|
vector.set(fabs(cameraPos.x() - pos.x()), fabs(cameraPos.y() - pos.y()), fabs(cameraPos.z() - pos.z()));
|
|
float distance = vector.magnitude();
|
|
float maxDistance = 8.0f;
|
|
int diffVolume = _maxVolume - _minVolume;
|
|
int newVolume = (int)(diffVolume * (1.0 - (distance / maxDistance)));
|
|
newVolume += _minVolume;
|
|
g_imuse->setVolume(soundName, newVolume);
|
|
|
|
//TODO
|
|
//g_imuse->setPan(soundName, pan);
|
|
}
|
|
|
|
void Scene::setSoundParameters(int minVolume, int maxVolume) {
|
|
_minVolume = minVolume;
|
|
_maxVolume = maxVolume;
|
|
}
|
|
|
|
void Scene::getSoundParameters(int *minVolume, int *maxVolume) {
|
|
*minVolume = _minVolume;
|
|
*maxVolume = _maxVolume;
|
|
}
|