FREESCAPE: initial parsing and rendering of group objects

This commit is contained in:
neuromancer 2023-05-17 10:11:11 +02:00
parent e96d2199c3
commit d0f9025cb9
9 changed files with 153 additions and 11 deletions

View file

@ -226,11 +226,20 @@ void Area::draw(Freescape::Renderer *gfx) {
assert(_drawableObjects.size() > 0);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
obj->draw(gfx);
if (obj->getType() != ObjectType::kGroupType)
obj->draw(gfx);
else
drawGroup(gfx, (Group *)obj);
}
}
}
void Area::drawGroup(Freescape::Renderer *gfx, Group* group) {
for (auto &obj : group->_objects) {
obj->draw(gfx);
}
}
Object *Area::shootRay(const Math::Ray &ray) {
float size = 16.0 * 8192.0; // TODO: check if this is max size
Object *collided = nullptr;

View file

@ -30,6 +30,8 @@
#include "freescape/language/instruction.h"
#include "freescape/objects/object.h"
#include "freescape/objects/group.h"
namespace Freescape {
@ -50,6 +52,7 @@ public:
void remapColor(int index, int color);
void unremapColor(int index);
void draw(Renderer *gfx);
void drawGroup(Renderer *gfx, Group *group);
void show();
Object *shootRay(const Math::Ray &ray);

View file

@ -286,6 +286,7 @@ public:
// Instructions
bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
bool checkIfGreaterOrEqual(FCLInstruction &instruction);
void executeExecute(FCLInstruction &instruction);
void executeIncrementVariable(FCLInstruction &instruction);
void executeDecrementVariable(FCLInstruction &instruction);
void executeSetVariable(FCLInstruction &instruction);

View file

@ -203,6 +203,9 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
case Token::REDRAW:
executeRedraw(instruction);
break;
case Token::EXECUTE:
executeExecute(instruction);
break;
case Token::DELAY:
executeDelay(instruction);
break;
@ -250,6 +253,12 @@ void FreescapeEngine::executeRedraw(FCLInstruction &instruction) {
waitForSounds();
}
void FreescapeEngine::executeExecute(FCLInstruction &instruction) {
// TODO
uint16 objId = instruction._source;
debugC(1, kFreescapeDebugCode, "Executing instructions from object %d", objId);
}
void FreescapeEngine::executeSound(FCLInstruction &instruction) {
if (_firstSound)
stopAllSounds();

View file

@ -277,11 +277,23 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
case kGroupType:
debugC(1, kFreescapeDebugParser, "Object of type 'group'");
file->seek(byteSizeOfObject, SEEK_CUR);
Common::Array<uint8> groupDataArray;
groupDataArray.push_back(uint8(position.x()));
groupDataArray.push_back(uint8(position.y()));
groupDataArray.push_back(uint8(position.z()));
groupDataArray.push_back(uint8(v.x()));
groupDataArray.push_back(uint8(v.y()));
groupDataArray.push_back(uint8(v.z()));
byteSizeOfObject++;
while(--byteSizeOfObject > 0)
groupDataArray.push_back(file->readByte());
return new Group(
objectID,
position,
v);
rawFlagsAndType,
groupDataArray);
break;
}
// Unreachable
@ -486,6 +498,12 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
debugC(1, kFreescapeDebugParser, "Reading object: %d", object);
Object *newObject = load8bitObject(file);
if (newObject->getType() == ObjectType::kGroupType) {
Group *group = (Group *)newObject;
for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
group->assemble(it->_value);
}
if (newObject) {
newObject->scale(scale);
if (newObject->getType() == kEntranceType) {

View file

@ -26,6 +26,7 @@ MODULE_OBJS := \
movement.o \
neo.o \
objects/geometricobject.o \
objects/group.o \
objects/sensor.o \
scr.o \
sound.o \

View file

@ -171,6 +171,16 @@ GeometricObject::GeometricObject(
}
void GeometricObject::setOrigin(Math::Vector3d origin_) {
if (isPolygon(_type)) {
Math::Vector3d offset = origin_ - _origin;
offset = 32 * offset;
for (int i = 0; i < int(_ordinates->size()); i = i + 3) {
(*_ordinates)[i ] += uint16(offset.x());
(*_ordinates)[i + 1] += uint16(offset.y());
(*_ordinates)[i + 2] += uint16(offset.z());
}
}
_origin = origin_;
computeBoundingBox();
}

View file

@ -0,0 +1,90 @@
/* 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.
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "freescape/freescape.h"
#include "freescape/objects/group.h"
#include "freescape/objects/geometricobject.h"
namespace Freescape {
Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
_objectID = objectID_;
_flags = flags_;
int i;
for (i = 0; i < 9; i++) {
debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
if (data_[i] > 0)
_objectIds.push_back(data_[i]);
/*else
break;*/
}
i = 9;
while (i < int(data_.size())) {
debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
if (data_[i] >= _objectIds.size())
break;
_objects.push_back(nullptr);
//assert(data_[i] < _objectIds.size());
_objectIndices.push_back(data_[i]);
debug("data[%d] = %d", i + 1, data_[i + 1]);
debug("data[%d] = %d", i + 2, data_[i + 2]);
debug("data[%d] = %d", i + 3, data_[i + 3]);
Math::Vector3d position(data_[i + 1], data_[i + 2], data_[i + 3]);
_objectPositions.push_back(position);
i = i + 4;
}
if (isDestroyed()) // If the object is destroyed, restore it
restore();
_flags = _flags & ~0x80;
assert(!isInitiallyInvisible());
makeVisible();
}
void Group::assemble(Object *obj) {
int objectIndex = -1;
for (int i = 0; i < int(_objectIds.size()) ; i++) {
if (_objectIds[i] == obj->getObjectID()) {
objectIndex = i;
break;
}
}
if (objectIndex == -1)
return;
for (int i = 0; i < int(_objectIndices.size()) ; i++) {
int index = _objectIndices[i];
if (index == objectIndex) {
Object *duplicate = obj->duplicate();
Math::Vector3d position = _objectPositions[i];
duplicate->setOrigin(position);
_objects[i] = duplicate;
}
}
}
} // End of namespace Freescape

View file

@ -28,15 +28,16 @@ namespace Freescape {
class Group : public Object {
public:
Group(uint16 objectID_,
const Math::Vector3d &origin_,
const Math::Vector3d &rotation_) {
_objectID = objectID_;
_origin = origin_;
_rotation = rotation_;
}
Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_);
void assemble(Object *obj);
Common::Array<Object *> _objects;
Common::Array<Math::Vector3d> _objectPositions;
Common::Array<int16> _objectIndices;
Common::Array<int16> _objectIds;
ObjectType getType() override { return ObjectType::kGroupType; };
bool isDrawable() override { return true; }
void draw(Freescape::Renderer *gfx) override { error("cannot render Group"); };
void scale(int factor) override { warning("cannot scale Group"); };
Object *duplicate() override { error("cannot duplicate Group"); };