2009-09-15 17:53:36 +02:00
|
|
|
/* Residual - A 3D game interpreter
|
|
|
|
*
|
|
|
|
* Residual is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2011-09-03 15:39:16 +02:00
|
|
|
#include "engines/myst3/node.h"
|
2011-12-29 14:39:36 +01:00
|
|
|
#include "engines/myst3/myst3.h"
|
|
|
|
#include "engines/myst3/variables.h"
|
2009-09-15 17:53:36 +02:00
|
|
|
|
2009-09-17 13:40:15 +02:00
|
|
|
#include "common/debug.h"
|
2011-08-28 20:10:47 +02:00
|
|
|
#include "common/rect.h"
|
2009-09-17 13:40:15 +02:00
|
|
|
|
2009-09-15 17:53:36 +02:00
|
|
|
namespace Myst3 {
|
|
|
|
|
2011-12-26 21:39:26 +01:00
|
|
|
void Face::setTextureFromJPEG(Graphics::JPEG *jpeg) {
|
|
|
|
_bitmap = new Graphics::Surface();
|
|
|
|
_bitmap->create(jpeg->getComponent(1)->w, jpeg->getComponent(1)->h, Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
|
2009-09-15 17:53:36 +02:00
|
|
|
|
|
|
|
byte *y = (byte *)jpeg->getComponent(1)->getBasePtr(0, 0);
|
|
|
|
byte *u = (byte *)jpeg->getComponent(2)->getBasePtr(0, 0);
|
|
|
|
byte *v = (byte *)jpeg->getComponent(3)->getBasePtr(0, 0);
|
|
|
|
|
2011-12-26 21:39:26 +01:00
|
|
|
byte *ptr = (byte *)_bitmap->getBasePtr(0, 0);
|
|
|
|
for (int i = 0; i < _bitmap->w * _bitmap->h; i++) {
|
2009-09-15 17:53:36 +02:00
|
|
|
byte r, g, b;
|
|
|
|
Graphics::YUV2RGB(*y++, *u++, *v++, r, g, b);
|
|
|
|
*ptr++ = r;
|
|
|
|
*ptr++ = g;
|
|
|
|
*ptr++ = b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 20:04:14 +01:00
|
|
|
Face::Face() {
|
2011-12-26 21:39:26 +01:00
|
|
|
glGenTextures(1, &_textureId);
|
2009-09-15 17:53:36 +02:00
|
|
|
|
2011-12-26 21:39:26 +01:00
|
|
|
glBindTexture(GL_TEXTURE_2D, _textureId);
|
2009-09-15 17:53:36 +02:00
|
|
|
|
2011-12-26 21:39:26 +01:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, Node::_cubeTextureSize, Node::_cubeTextureSize, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
2009-09-15 17:53:36 +02:00
|
|
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
}
|
|
|
|
|
2011-12-26 21:39:26 +01:00
|
|
|
void Face::uploadTexture() {
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _textureId);
|
|
|
|
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _bitmap->w, _bitmap->h, GL_RGB, GL_UNSIGNED_BYTE, _bitmap->pixels);
|
|
|
|
}
|
|
|
|
|
2011-12-29 20:04:14 +01:00
|
|
|
Face::~Face() {
|
2011-12-26 21:39:26 +01:00
|
|
|
_bitmap->free();
|
|
|
|
delete _bitmap;
|
|
|
|
_bitmap = 0;
|
|
|
|
|
|
|
|
glDeleteTextures(1, &_textureId);
|
|
|
|
}
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
Node::Node(Myst3Engine *vm, Archive *archive, uint16 id) :
|
|
|
|
_vm(vm) {
|
2011-12-29 20:04:14 +01:00
|
|
|
for (uint i = 0; i < 6; i++)
|
|
|
|
_faces[i] = 0;
|
2011-12-29 11:38:49 +01:00
|
|
|
}
|
|
|
|
|
2011-09-03 15:39:16 +02:00
|
|
|
void Node::dumpFaceMask(Archive &archive, uint16 index, int face) {
|
2009-09-17 13:40:15 +02:00
|
|
|
byte *mask = new byte[640 * 640];
|
|
|
|
memset(mask, 0, sizeof(mask));
|
|
|
|
uint32 headerOffset = 0;
|
|
|
|
uint32 dataOffset = 0;
|
|
|
|
|
2011-09-11 10:15:41 +02:00
|
|
|
const DirectorySubEntry *maskDesc = archive.getDescription(index, face, DirectorySubEntry::kFaceMask);
|
|
|
|
Common::MemoryReadStream *maskStream = archive.getData(maskDesc);
|
2009-09-17 13:40:15 +02:00
|
|
|
|
|
|
|
while (headerOffset < 400) {
|
|
|
|
int blockX = (headerOffset / sizeof(dataOffset)) % 10;
|
|
|
|
int blockY = (headerOffset / sizeof(dataOffset)) / 10;
|
|
|
|
|
|
|
|
maskStream->seek(headerOffset, SEEK_SET);
|
|
|
|
dataOffset = maskStream->readUint32LE();
|
|
|
|
headerOffset = maskStream->pos();
|
|
|
|
|
|
|
|
if (dataOffset != 0) {
|
|
|
|
maskStream->seek(dataOffset, SEEK_SET);
|
|
|
|
|
|
|
|
for(int i = 63; i >= 0; i--) {
|
|
|
|
int x = 0;
|
|
|
|
byte numValues = maskStream->readByte();
|
|
|
|
for (int j = 0; j < numValues; j++) {
|
|
|
|
byte repeat = maskStream->readByte();
|
|
|
|
byte value = maskStream->readByte();
|
|
|
|
for (int k = 0; k < repeat; k++) {
|
|
|
|
mask[((blockY * 64) + i) * 640 + blockX * 64 + x] = value;
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-11 10:15:41 +02:00
|
|
|
delete maskStream;
|
|
|
|
|
2009-09-17 13:40:15 +02:00
|
|
|
Common::DumpFile outFile;
|
|
|
|
outFile.open("dump/1-1.masku");
|
|
|
|
outFile.write(mask, sizeof(mask));
|
|
|
|
outFile.close();
|
|
|
|
delete[] mask;
|
|
|
|
}
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
Node::~Node() {
|
2011-12-27 15:15:17 +01:00
|
|
|
for (uint i = 0; i < _spotItems.size(); i++) {
|
|
|
|
delete _spotItems[i];
|
|
|
|
}
|
|
|
|
_spotItems.clear();
|
|
|
|
|
2011-08-28 20:10:47 +02:00
|
|
|
for (int i = 0; i < 6; i++) {
|
2011-12-29 20:04:14 +01:00
|
|
|
delete _faces[i];
|
2011-08-28 20:10:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-27 15:15:17 +01:00
|
|
|
void Node::loadSpotItem(Archive &archive, uint16 id, uint16 condition, bool fade) {
|
2011-12-29 11:38:49 +01:00
|
|
|
SpotItem *spotItem = new SpotItem(_vm);
|
2011-12-27 15:15:17 +01:00
|
|
|
|
|
|
|
spotItem->setCondition(condition);
|
|
|
|
spotItem->setFade(fade);
|
|
|
|
spotItem->setFadeVar(abs(condition));
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
const DirectorySubEntry *jpegDesc = archive.getDescription(id, i + 1, DirectorySubEntry::kSpotItem);
|
|
|
|
|
|
|
|
if (!jpegDesc) continue;
|
|
|
|
|
|
|
|
SpotItemFace *spotItemFace = new SpotItemFace(
|
2011-12-29 20:04:14 +01:00
|
|
|
_faces[i],
|
2011-12-27 15:15:17 +01:00
|
|
|
jpegDesc->getSpotItemData().u,
|
|
|
|
jpegDesc->getSpotItemData().v);
|
|
|
|
|
|
|
|
Common::MemoryReadStream *jpegStream = archive.getData(jpegDesc);
|
|
|
|
|
|
|
|
Graphics::JPEG jpeg;
|
|
|
|
jpeg.read(jpegStream);
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
spotItemFace->loadData(&jpeg);
|
2011-12-27 15:15:17 +01:00
|
|
|
|
|
|
|
delete jpegStream;
|
|
|
|
|
|
|
|
spotItem->addFace(spotItemFace);
|
|
|
|
}
|
|
|
|
|
|
|
|
_spotItems.push_back(spotItem);
|
|
|
|
}
|
|
|
|
|
2011-12-29 14:39:36 +01:00
|
|
|
void Node::update() {
|
|
|
|
for (uint i = 0; i < _spotItems.size(); i++) {
|
|
|
|
_spotItems[i]->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
SpotItem::SpotItem(Myst3Engine *vm) :
|
|
|
|
_vm(vm) {
|
|
|
|
}
|
|
|
|
|
2011-12-27 15:15:17 +01:00
|
|
|
SpotItem::~SpotItem() {
|
|
|
|
for (uint i = 0; i < _faces.size(); i++) {
|
|
|
|
delete _faces[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 14:39:36 +01:00
|
|
|
void SpotItem::update() {
|
|
|
|
// First undraw ...
|
|
|
|
for (uint i = 0; i < _faces.size(); i++) {
|
|
|
|
if (!_vm->_vars->evaluate(_condition) && _faces[i]->isDrawn()) {
|
|
|
|
_faces[i]->undraw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ... then redraw
|
|
|
|
for (uint i = 0; i < _faces.size(); i++) {
|
|
|
|
uint16 newFadeValue = _vm->_vars->get(_fadeVar);
|
|
|
|
|
|
|
|
if (_enableFade && _faces[i]->getFadeValue() != newFadeValue) {
|
|
|
|
_faces[i]->setFadeValue(newFadeValue);
|
|
|
|
_faces[i]->setDrawn(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vm->_vars->evaluate(_condition) && !_faces[i]->isDrawn()) {
|
|
|
|
if (_enableFade)
|
|
|
|
_faces[i]->fadeDraw();
|
|
|
|
else
|
|
|
|
_faces[i]->draw();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
SpotItemFace::SpotItemFace(Face *face, uint16 posX, uint16 posY):
|
2011-12-27 15:15:17 +01:00
|
|
|
_face(face),
|
|
|
|
_posX(posX),
|
|
|
|
_posY(posY),
|
|
|
|
_drawn(false),
|
|
|
|
_bitmap(0),
|
|
|
|
_notDrawnBitmap(0),
|
|
|
|
_fadeValue(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SpotItemFace::~SpotItemFace() {
|
|
|
|
if (_bitmap) {
|
|
|
|
_bitmap->free();
|
|
|
|
delete _bitmap;
|
|
|
|
_bitmap = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_notDrawnBitmap) {
|
|
|
|
_notDrawnBitmap->free();
|
|
|
|
delete _notDrawnBitmap;
|
|
|
|
_notDrawnBitmap = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 11:38:49 +01:00
|
|
|
void SpotItemFace::loadData(Graphics::JPEG *jpeg) {
|
2011-12-27 15:15:17 +01:00
|
|
|
// Convert active SpotItem image to raw data
|
|
|
|
_bitmap = new Graphics::Surface();
|
|
|
|
_bitmap->create(jpeg->getComponent(1)->w, jpeg->getComponent(1)->h, Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
|
|
|
|
|
2011-12-29 14:39:36 +01:00
|
|
|
for (int i = 0; i < _bitmap->h; i++) {
|
|
|
|
byte *y = (byte *)jpeg->getComponent(1)->getBasePtr(0, i);
|
|
|
|
byte *u = (byte *)jpeg->getComponent(2)->getBasePtr(0, i);
|
|
|
|
byte *v = (byte *)jpeg->getComponent(3)->getBasePtr(0, i);
|
2011-12-27 15:15:17 +01:00
|
|
|
|
2011-12-29 14:39:36 +01:00
|
|
|
byte *ptr = (byte *)_bitmap->getBasePtr(0, i);
|
|
|
|
|
|
|
|
for (int j = 0; j < _bitmap->w; j++) {
|
|
|
|
byte r, g, b;
|
|
|
|
Graphics::YUV2RGB(*y++, *u++, *v++, r, g, b);
|
|
|
|
*ptr++ = r;
|
|
|
|
*ptr++ = g;
|
|
|
|
*ptr++ = b;
|
|
|
|
}
|
2011-12-27 15:15:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Copy not drawn SpotItem image from face
|
|
|
|
_notDrawnBitmap = new Graphics::Surface();
|
|
|
|
_notDrawnBitmap->create(jpeg->getComponent(1)->w, jpeg->getComponent(1)->h, Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0));
|
|
|
|
|
|
|
|
for (uint i = 0; i < _notDrawnBitmap->h; i++) {
|
|
|
|
memcpy(_notDrawnBitmap->getBasePtr(0, i),
|
2011-12-29 11:38:49 +01:00
|
|
|
_face->_bitmap->getBasePtr(_posX, _posY + i),
|
2011-12-27 15:15:17 +01:00
|
|
|
_notDrawnBitmap->w * 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 14:39:36 +01:00
|
|
|
void SpotItemFace::draw() {
|
|
|
|
for (uint i = 0; i < _bitmap->h; i++) {
|
|
|
|
memcpy(_face->_bitmap->getBasePtr(_posX, _posY + i),
|
|
|
|
_bitmap->getBasePtr(0, i),
|
|
|
|
_bitmap->w * 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
_drawn = true;
|
|
|
|
|
|
|
|
// TODO: Upload the texture at most once per frame
|
|
|
|
_face->uploadTexture();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotItemFace::undraw() {
|
|
|
|
for (uint i = 0; i < _notDrawnBitmap->h; i++) {
|
|
|
|
memcpy(_face->_bitmap->getBasePtr(_posX, _posY + i),
|
|
|
|
_notDrawnBitmap->getBasePtr(0, i),
|
|
|
|
_notDrawnBitmap->w * 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
_drawn = false;
|
|
|
|
|
|
|
|
// TODO: Upload the texture at most once per frame
|
|
|
|
_face->uploadTexture();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpotItemFace::fadeDraw() {
|
|
|
|
for (int i = 0; i < _bitmap->h; i++) {
|
|
|
|
byte *ptrND = (byte *)_notDrawnBitmap->getBasePtr(0, i);
|
|
|
|
byte *ptrD = (byte *)_bitmap->getBasePtr(0, i);
|
|
|
|
byte *ptrDest = (byte *)_face->_bitmap->getBasePtr(_posX, _posY + i);
|
|
|
|
|
|
|
|
for (int j = 0; j < _bitmap->w; j++) {
|
|
|
|
byte rND = *ptrND++;
|
|
|
|
byte gND = *ptrND++;
|
|
|
|
byte bND = *ptrND++;
|
|
|
|
byte rD = *ptrD++;
|
|
|
|
byte gD = *ptrD++;
|
|
|
|
byte bD = *ptrD++;
|
|
|
|
|
|
|
|
// TODO: optimize ?
|
|
|
|
*ptrDest++ = rND * (100 - _fadeValue) / 100 + rD * _fadeValue / 100;
|
|
|
|
*ptrDest++ = gND * (100 - _fadeValue) / 100 + gD * _fadeValue / 100;
|
|
|
|
*ptrDest++ = bND * (100 - _fadeValue) / 100 + bD * _fadeValue / 100;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_drawn = true;
|
|
|
|
|
|
|
|
// TODO: Upload the texture at most once per frame
|
|
|
|
_face->uploadTexture();
|
|
|
|
}
|
|
|
|
|
2009-09-15 17:53:36 +02:00
|
|
|
} // end of namespace Myst3
|