TWINE: use BodyData for rendering
This commit is contained in:
parent
cdc6281bd0
commit
33371ae454
16 changed files with 232 additions and 393 deletions
|
@ -259,12 +259,12 @@ void Holomap::drawHolomapText(int32 centerx, int32 top, const char *title) {
|
||||||
_engine->_text->drawText(x, y, title);
|
_engine->_text->drawText(x, y, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Holomap::renderHolomapModel(const uint8 *bodyPtr, int32 x, int32 y, int32 zPos) {
|
void Holomap::renderHolomapModel(const BodyData &bodyData, int32 x, int32 y, int32 zPos) {
|
||||||
_engine->_renderer->setBaseRotation(x, y, 0);
|
_engine->_renderer->setBaseRotation(x, y, 0);
|
||||||
_engine->_renderer->getBaseRotationPosition(0, 0, zPos + 1000);
|
_engine->_renderer->getBaseRotationPosition(0, 0, zPos + 1000);
|
||||||
_engine->_renderer->getBaseRotationPosition(_engine->_renderer->destPos.x, _engine->_renderer->destPos.y, _engine->_renderer->destPos.z);
|
_engine->_renderer->getBaseRotationPosition(_engine->_renderer->destPos.x, _engine->_renderer->destPos.y, _engine->_renderer->destPos.z);
|
||||||
_engine->_interface->resetClip();
|
_engine->_interface->resetClip();
|
||||||
_engine->_renderer->renderIsoModel(_engine->_renderer->destPos.x, _engine->_renderer->destPos.y, _engine->_renderer->destPos.z, x, y, 0, bodyPtr);
|
_engine->_renderer->renderIsoModel(_engine->_renderer->destPos.x, _engine->_renderer->destPos.y, _engine->_renderer->destPos.z, x, y, 0, bodyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
||||||
|
@ -296,8 +296,8 @@ void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
||||||
AnimTimerDataStruct animTimerData;
|
AnimTimerDataStruct animTimerData;
|
||||||
AnimData animData;
|
AnimData animData;
|
||||||
animData.loadFromHQR(Resources::HQR_RESS_FILE, data->getAnimation());
|
animData.loadFromHQR(Resources::HQR_RESS_FILE, data->getAnimation());
|
||||||
uint8 *modelPtr = nullptr;
|
BodyData bodyData;
|
||||||
HQR::getAllocEntry(&modelPtr, Resources::HQR_RESS_FILE, data->getModel());
|
bodyData.loadFromHQR(Resources::HQR_RESS_FILE, data->getModel());
|
||||||
uint frameNumber = 0;
|
uint frameNumber = 0;
|
||||||
int32 frameTime = _engine->lbaTime;
|
int32 frameTime = _engine->lbaTime;
|
||||||
int16 trajAnimFrameIdx = 0;
|
int16 trajAnimFrameIdx = 0;
|
||||||
|
@ -329,7 +329,7 @@ void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
||||||
_engine->_movements->setActorAngleSafe(ANGLE_0, -ANGLE_90, 500, &move);
|
_engine->_movements->setActorAngleSafe(ANGLE_0, -ANGLE_90, 500, &move);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_engine->_animations->setModelAnimation(frameNumber, animData, modelPtr, &animTimerData)) {
|
if (_engine->_animations->setModelAnimation(frameNumber, animData, bodyData, &animTimerData)) {
|
||||||
frameNumber++;
|
frameNumber++;
|
||||||
if (frameNumber >= animData.getNumKeyframes()) {
|
if (frameNumber >= animData.getNumKeyframes()) {
|
||||||
frameNumber = animData.getLoopFrame();
|
frameNumber = animData.getLoopFrame();
|
||||||
|
@ -340,7 +340,7 @@ void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
||||||
_engine->_renderer->setLightVector(-60, 128, 0);
|
_engine->_renderer->setLightVector(-60, 128, 0);
|
||||||
const Common::Rect rect(0, 200, 199, 479);
|
const Common::Rect rect(0, 200, 199, 479);
|
||||||
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
|
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
|
||||||
_engine->_renderer->renderIsoModel(0, 0, 0, 0, newAngle, 0, modelPtr);
|
_engine->_renderer->renderIsoModel(0, 0, 0, 0, newAngle, 0, bodyData);
|
||||||
_engine->copyBlockPhys(rect);
|
_engine->copyBlockPhys(rect);
|
||||||
_engine->_renderer->setCameraPosition(400, 240, 128, 1024, 1024);
|
_engine->_renderer->setCameraPosition(400, 240, 128, 1024, 1024);
|
||||||
_engine->_renderer->setCameraAngle(0, 0, 0, data->pos.x, data->pos.y, data->pos.z, 5300);
|
_engine->_renderer->setCameraAngle(0, 0, 0, data->pos.x, data->pos.y, data->pos.z, 5300);
|
||||||
|
@ -377,7 +377,6 @@ void Holomap::drawHolomapTrajectory(int32 trajectoryIndex) {
|
||||||
|
|
||||||
_engine->_text->initSceneTextBank();
|
_engine->_text->initSceneTextBank();
|
||||||
_engine->_input->enableKeyMap(mainKeyMapId);
|
_engine->_input->enableKeyMap(mainKeyMapId);
|
||||||
free(modelPtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Holomap::getNextHolomapLocation(int32 currentLocation, int32 dir) const {
|
int32 Holomap::getNextHolomapLocation(int32 currentLocation, int32 dir) const {
|
||||||
|
@ -445,18 +444,18 @@ void Holomap::renderLocations(int xRot, int yRot, int zRot, bool lower) {
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
const DrawListStruct &drawList = _engine->_redraw->drawList[i];
|
const DrawListStruct &drawList = _engine->_redraw->drawList[i];
|
||||||
const uint16 flags = drawList.type;
|
const uint16 flags = drawList.type;
|
||||||
const uint8 *bodyPtr = nullptr;
|
const BodyData *bodyData = nullptr;
|
||||||
if (flags == 1u) {
|
if (flags == 1u) {
|
||||||
bodyPtr = _engine->_resources->holomapArrowPtr;
|
bodyData = &_engine->_resources->holomapArrowPtr;
|
||||||
} else if (flags == 2u) {
|
} else if (flags == 2u) {
|
||||||
bodyPtr = _engine->_resources->holomapTwinsenModelPtr;
|
bodyData = &_engine->_resources->holomapTwinsenModelPtr;
|
||||||
} else if (flags == 3u) {
|
} else if (flags == 3u) {
|
||||||
bodyPtr = _engine->_resources->holomapTwinsenArrowPtr;
|
bodyData = &_engine->_resources->holomapTwinsenArrowPtr;
|
||||||
}
|
}
|
||||||
if (bodyPtr != nullptr) {
|
if (bodyData != nullptr) {
|
||||||
int32 angleX = _locations[drawList.actorIdx].angle.x;
|
int32 angleX = _locations[drawList.actorIdx].angle.x;
|
||||||
int32 angleY = _locations[drawList.actorIdx].angle.y;
|
int32 angleY = _locations[drawList.actorIdx].angle.y;
|
||||||
_engine->_renderer->renderIsoModel(drawList.x, drawList.y, drawList.z, angleX, angleY, 0, bodyPtr);
|
_engine->_renderer->renderIsoModel(drawList.x, drawList.y, drawList.z, angleX, angleY, 0, *bodyData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ private:
|
||||||
|
|
||||||
void renderLocations(int xRot, int yRot, int zRot, bool lower);
|
void renderLocations(int xRot, int yRot, int zRot, bool lower);
|
||||||
|
|
||||||
void renderHolomapModel(const uint8 *bodyPtr, int32 x, int32 y, int32 zPos);
|
void renderHolomapModel(const BodyData &bodyData, int32 x, int32 y, int32 zPos);
|
||||||
|
|
||||||
void prepareHolomapSurface();
|
void prepareHolomapSurface();
|
||||||
void prepareHolomapProjectedPositions();
|
void prepareHolomapProjectedPositions();
|
||||||
|
|
|
@ -918,7 +918,7 @@ void Menu::drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int
|
||||||
|
|
||||||
uint currentAnimState = behaviourAnimState[(byte)behaviour];
|
uint currentAnimState = behaviourAnimState[(byte)behaviour];
|
||||||
|
|
||||||
if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, behaviourEntity, &behaviourAnimData[(byte)behaviour])) {
|
if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, *behaviourEntity, &behaviourAnimData[(byte)behaviour])) {
|
||||||
currentAnimState++; // keyframe
|
currentAnimState++; // keyframe
|
||||||
if (currentAnimState >= currentAnimData.getNumKeyframes()) {
|
if (currentAnimState >= currentAnimData.getNumKeyframes()) {
|
||||||
currentAnimState = currentAnimData.getLoopFrame();
|
currentAnimState = currentAnimData.getLoopFrame();
|
||||||
|
@ -963,7 +963,7 @@ void Menu::drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int
|
||||||
_engine->_interface->drawFilledRect(boxRect, COLOR_BLACK);
|
_engine->_interface->drawFilledRect(boxRect, COLOR_BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
_engine->_renderer->renderBehaviourModel(boxRect, -600, angle, behaviourEntity);
|
_engine->_renderer->renderBehaviourModel(boxRect, -600, angle, *behaviourEntity);
|
||||||
|
|
||||||
if (dirtyRect.isEmpty()) {
|
if (dirtyRect.isEmpty()) {
|
||||||
dirtyRect = boxRect;
|
dirtyRect = boxRect;
|
||||||
|
@ -976,7 +976,7 @@ void Menu::drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int
|
||||||
|
|
||||||
void Menu::prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect) {
|
void Menu::prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect) {
|
||||||
const int animIdx = _engine->_actor->heroAnimIdx[(byte)behaviour];
|
const int animIdx = _engine->_actor->heroAnimIdx[(byte)behaviour];
|
||||||
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)behaviour], _engine->_resources->animData[animIdx], behaviourEntity, &behaviourAnimData[(byte)behaviour]);
|
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)behaviour], _engine->_resources->animData[animIdx], *behaviourEntity, &behaviourAnimData[(byte)behaviour]);
|
||||||
drawBehaviour(left, top, behaviour, angle, false, dirtyRect);
|
drawBehaviour(left, top, behaviour, angle, false, dirtyRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,7 +1011,7 @@ void Menu::processBehaviourMenu() {
|
||||||
_engine->_actor->setBehaviour(HeroBehaviourType::kNormal);
|
_engine->_actor->setBehaviour(HeroBehaviourType::kNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
behaviourEntity = _engine->_resources->bodyTable[_engine->_scene->sceneHero->entity];
|
behaviourEntity = &_engine->_resources->bodyData[_engine->_scene->sceneHero->entity];
|
||||||
|
|
||||||
_engine->_actor->heroAnimIdx[(byte)HeroBehaviourType::kNormal] = _engine->_actor->heroAnimIdxNORMAL;
|
_engine->_actor->heroAnimIdx[(byte)HeroBehaviourType::kNormal] = _engine->_actor->heroAnimIdxNORMAL;
|
||||||
_engine->_actor->heroAnimIdx[(byte)HeroBehaviourType::kAthletic] = _engine->_actor->heroAnimIdxATHLETIC;
|
_engine->_actor->heroAnimIdx[(byte)HeroBehaviourType::kAthletic] = _engine->_actor->heroAnimIdxATHLETIC;
|
||||||
|
@ -1034,7 +1034,7 @@ void Menu::processBehaviourMenu() {
|
||||||
HeroBehaviourType tmpHeroBehaviour = _engine->_actor->heroBehaviour;
|
HeroBehaviourType tmpHeroBehaviour = _engine->_actor->heroBehaviour;
|
||||||
|
|
||||||
const int animIdx = _engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour];
|
const int animIdx = _engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour];
|
||||||
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animData[animIdx], behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
|
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animData[animIdx], *behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
|
||||||
|
|
||||||
int32 tmpTime = _engine->lbaTime;
|
int32 tmpTime = _engine->lbaTime;
|
||||||
|
|
||||||
|
@ -1080,7 +1080,7 @@ void Menu::processBehaviourMenu() {
|
||||||
tmpHeroBehaviour = _engine->_actor->heroBehaviour;
|
tmpHeroBehaviour = _engine->_actor->heroBehaviour;
|
||||||
_engine->_movements->setActorAngleSafe(_engine->_scene->sceneHero->angle, _engine->_scene->sceneHero->angle - ANGLE_90, ANGLE_17, &moveMenu);
|
_engine->_movements->setActorAngleSafe(_engine->_scene->sceneHero->angle, _engine->_scene->sceneHero->angle - ANGLE_90, ANGLE_17, &moveMenu);
|
||||||
const int tmpAnimIdx = _engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour];
|
const int tmpAnimIdx = _engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour];
|
||||||
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animData[tmpAnimIdx], behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
|
_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animData[tmpAnimIdx], *behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawBehaviour(left, top, _engine->_actor->heroBehaviour, -1, true, dirtyRect);
|
drawBehaviour(left, top, _engine->_actor->heroBehaviour, -1, true, dirtyRect);
|
||||||
|
|
|
@ -137,7 +137,7 @@ class Menu {
|
||||||
private:
|
private:
|
||||||
TwinEEngine *_engine;
|
TwinEEngine *_engine;
|
||||||
/** Hero behaviour menu entity */
|
/** Hero behaviour menu entity */
|
||||||
uint8 *behaviourEntity = nullptr;
|
BodyData *behaviourEntity = nullptr;
|
||||||
/** Behaviour menu anim state */
|
/** Behaviour menu anim state */
|
||||||
uint behaviourAnimState[4]; // winTab
|
uint behaviourAnimState[4]; // winTab
|
||||||
/** Behaviour menu anim data pointer */
|
/** Behaviour menu anim data pointer */
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
namespace TwinE {
|
namespace TwinE {
|
||||||
|
|
||||||
struct BoneFrame {
|
struct BoneFrame {
|
||||||
|
/**
|
||||||
|
* 0 = allow global rotate
|
||||||
|
* 1 = disallow global rotate
|
||||||
|
* 2 = disallow global rotate and hide
|
||||||
|
*/
|
||||||
uint16 type = 0;
|
uint16 type = 0;
|
||||||
int16 x = 0;
|
int16 x = 0;
|
||||||
int16 y = 0;
|
int16 y = 0;
|
||||||
|
|
|
@ -64,6 +64,8 @@ void BodyData::loadBones(Common::SeekableReadStream &stream) {
|
||||||
BodyBone bone;
|
BodyBone bone;
|
||||||
bone.parent = baseElementOffset == -1 ? 0xffff : baseElementOffset / 38;
|
bone.parent = baseElementOffset == -1 ? 0xffff : baseElementOffset / 38;
|
||||||
bone.vertex = basePoint;
|
bone.vertex = basePoint;
|
||||||
|
bone.firstVertex = firstPoint;
|
||||||
|
bone.numVertices = numPoints;
|
||||||
bone.initalBoneState = boneframe;
|
bone.initalBoneState = boneframe;
|
||||||
bone.numOfShades = numOfShades;
|
bone.numOfShades = numOfShades;
|
||||||
|
|
||||||
|
@ -73,6 +75,7 @@ void BodyData::loadBones(Common::SeekableReadStream &stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_bones.push_back(bone);
|
_bones.push_back(bone);
|
||||||
|
_boneStates[i] = bone.initalBoneState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,18 +99,18 @@ void BodyData::loadPolygons(Common::SeekableReadStream &stream) {
|
||||||
_polygons.reserve(numPolygons);
|
_polygons.reserve(numPolygons);
|
||||||
for (uint16 i = 0; i < numPolygons; ++i) {
|
for (uint16 i = 0; i < numPolygons; ++i) {
|
||||||
BodyPolygon poly;
|
BodyPolygon poly;
|
||||||
poly.renderType = stream.readSByte();
|
poly.renderType = stream.readByte();
|
||||||
const int8 numVertex = stream.readSByte();
|
const uint8 numVertices = stream.readByte();
|
||||||
|
|
||||||
poly.color = stream.readUint16LE();
|
poly.color = stream.readSint16LE();
|
||||||
int16 intensity = -1;
|
int16 intensity = -1;
|
||||||
if (poly.renderType == POLYGONTYPE_GOURAUD || poly.renderType == POLYGONTYPE_DITHER) {
|
if (poly.renderType == POLYGONTYPE_GOURAUD || poly.renderType == POLYGONTYPE_DITHER) {
|
||||||
intensity = stream.readSint16LE();
|
intensity = stream.readSint16LE();
|
||||||
}
|
}
|
||||||
|
|
||||||
poly.indices.reserve(numVertex);
|
poly.indices.reserve(numVertices);
|
||||||
poly.intensities.reserve(numVertex);
|
poly.intensities.reserve(numVertices);
|
||||||
for (int k = 0; k < numVertex; ++k) {
|
for (int k = 0; k < numVertices; ++k) {
|
||||||
if (poly.renderType >= POLYGONTYPE_UNKNOWN) {
|
if (poly.renderType >= POLYGONTYPE_UNKNOWN) {
|
||||||
intensity = stream.readSint16LE();
|
intensity = stream.readSint16LE();
|
||||||
}
|
}
|
||||||
|
@ -126,8 +129,9 @@ void BodyData::loadLines(Common::SeekableReadStream &stream) {
|
||||||
_lines.reserve(numLines);
|
_lines.reserve(numLines);
|
||||||
for (uint16 i = 0; i < numLines; ++i) {
|
for (uint16 i = 0; i < numLines; ++i) {
|
||||||
BodyLine line;
|
BodyLine line;
|
||||||
line.unk1 = stream.readUint16LE();
|
line.color = stream.readByte();
|
||||||
line.color = stream.readUint16LE();
|
line.unk1 = stream.readByte();
|
||||||
|
line.unk2 = stream.readUint16LE();
|
||||||
line.vertex1 = stream.readUint16LE() / 6;
|
line.vertex1 = stream.readUint16LE() / 6;
|
||||||
line.vertex2 = stream.readUint16LE() / 6;
|
line.vertex2 = stream.readUint16LE() / 6;
|
||||||
_lines.push_back(line);
|
_lines.push_back(line);
|
||||||
|
@ -140,9 +144,10 @@ void BodyData::loadSpheres(Common::SeekableReadStream &stream) {
|
||||||
_spheres.reserve(numSpheres);
|
_spheres.reserve(numSpheres);
|
||||||
for (uint16 i = 0; i < numSpheres; ++i) {
|
for (uint16 i = 0; i < numSpheres; ++i) {
|
||||||
BodySphere sphere;
|
BodySphere sphere;
|
||||||
|
sphere.unk1 = stream.readByte();
|
||||||
|
sphere.color = stream.readByte();
|
||||||
|
sphere.unk2 = stream.readUint16LE();
|
||||||
sphere.radius = stream.readUint16LE();
|
sphere.radius = stream.readUint16LE();
|
||||||
sphere.color = stream.readUint16LE();
|
|
||||||
sphere.size = stream.readUint16LE();
|
|
||||||
sphere.vertex = stream.readUint16LE() / 6;
|
sphere.vertex = stream.readUint16LE() / 6;
|
||||||
_spheres.push_back(sphere);
|
_spheres.push_back(sphere);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct BodyVertex {
|
||||||
struct BodyBone {
|
struct BodyBone {
|
||||||
uint16 parent;
|
uint16 parent;
|
||||||
uint16 vertex;
|
uint16 vertex;
|
||||||
|
int16 firstVertex;
|
||||||
|
int16 numVertices;
|
||||||
int32 numOfShades;
|
int32 numOfShades;
|
||||||
BoneFrame initalBoneState;
|
BoneFrame initalBoneState;
|
||||||
|
|
||||||
|
@ -61,20 +63,22 @@ struct BodyPolygon {
|
||||||
Common::Array<uint16> indices;
|
Common::Array<uint16> indices;
|
||||||
Common::Array<uint16> intensities;
|
Common::Array<uint16> intensities;
|
||||||
int8 renderType = 0;
|
int8 renderType = 0;
|
||||||
uint16 color = 0;
|
int16 color = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BodyLine {
|
struct BodyLine {
|
||||||
uint16 unk1;
|
uint8 color;
|
||||||
uint16 color;
|
uint8 unk1;
|
||||||
|
uint16 unk2;
|
||||||
uint16 vertex1;
|
uint16 vertex1;
|
||||||
uint16 vertex2;
|
uint16 vertex2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BodySphere {
|
struct BodySphere {
|
||||||
|
uint8 unk1;
|
||||||
|
uint8 color;
|
||||||
|
uint16 unk2;
|
||||||
uint16 radius;
|
uint16 radius;
|
||||||
uint16 color;
|
|
||||||
uint16 size;
|
|
||||||
uint16 vertex;
|
uint16 vertex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,8 +162,8 @@ public:
|
||||||
return _shades;
|
return _shades;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BodyShade* getShade(int16 shadeIdx) const {
|
const BodyShade &getShade(int16 shadeIdx) const {
|
||||||
return &_shades[shadeIdx];
|
return _shades[shadeIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Common::Array<BodyLine> &getLines() const {
|
const Common::Array<BodyLine> &getLines() const {
|
||||||
|
@ -170,8 +174,8 @@ public:
|
||||||
return _bones;
|
return _bones;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BodyBone* getBone(int16 boneIdx) const {
|
const BodyBone &getBone(int16 boneIdx) const {
|
||||||
return &_bones[boneIdx];
|
return _bones[boneIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadFromStream(Common::SeekableReadStream &stream) override;
|
bool loadFromStream(Common::SeekableReadStream &stream) override;
|
||||||
|
|
|
@ -343,13 +343,13 @@ void Redraw::processDrawListActors(const DrawListStruct &drawCmd, bool bgRedraw)
|
||||||
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
||||||
if (actor->previousAnimIdx >= 0) {
|
if (actor->previousAnimIdx >= 0) {
|
||||||
const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
|
const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
|
||||||
_engine->_animations->setModelAnimation(actor->animPosition, animData, _engine->_resources->bodyTable[actor->entity], &actor->animTimerData);
|
_engine->_animations->setModelAnimation(actor->animPosition, animData, _engine->_resources->bodyData[actor->entity], &actor->animTimerData);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32 x = actor->pos.x - _engine->_grid->camera.x;
|
const int32 x = actor->pos.x - _engine->_grid->camera.x;
|
||||||
const int32 y = actor->pos.y - _engine->_grid->camera.y;
|
const int32 y = actor->pos.y - _engine->_grid->camera.y;
|
||||||
const int32 z = actor->pos.z - _engine->_grid->camera.z;
|
const int32 z = actor->pos.z - _engine->_grid->camera.z;
|
||||||
if (!_engine->_renderer->renderIsoModel(x, y, z, ANGLE_0, actor->angle, ANGLE_0, _engine->_resources->bodyTable[actor->entity])) {
|
if (!_engine->_renderer->renderIsoModel(x, y, z, ANGLE_0, actor->angle, ANGLE_0, _engine->_resources->bodyData[actor->entity])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,7 +623,7 @@ void Redraw::renderOverlays() {
|
||||||
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
|
_engine->_interface->drawFilledRect(rect, COLOR_BLACK);
|
||||||
_engine->_interface->setClip(rect);
|
_engine->_interface->setClip(rect);
|
||||||
|
|
||||||
const uint8* bodyPtr = _engine->_resources->inventoryTable[item];
|
const BodyData &bodyPtr = _engine->_resources->inventoryTable[item];
|
||||||
_overlayRotation += 1; // overlayRotation += 8;
|
_overlayRotation += 1; // overlayRotation += 8;
|
||||||
_engine->_renderer->renderInventoryItem(40, 40, bodyPtr, _overlayRotation, 16000);
|
_engine->_renderer->renderInventoryItem(40, 40, bodyPtr, _overlayRotation, 16000);
|
||||||
_engine->_menu->drawBox(rect);
|
_engine->_menu->drawBox(rect);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "twine/menu/interface.h"
|
#include "twine/menu/interface.h"
|
||||||
#include "twine/menu/menu.h"
|
#include "twine/menu/menu.h"
|
||||||
|
#include "twine/parser/body.h"
|
||||||
#include "twine/renderer/redraw.h"
|
#include "twine/renderer/redraw.h"
|
||||||
#include "twine/renderer/shadeangletab.h"
|
#include "twine/renderer/shadeangletab.h"
|
||||||
#include "twine/resources/resources.h"
|
#include "twine/resources/resources.h"
|
||||||
|
@ -313,26 +314,24 @@ void Renderer::applyRotation(IMatrix3x3 *targetMatrix, const IMatrix3x3 *current
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::applyPointsRotation(const I16Vec3 *pointsPtr, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *rotationMatrix) {
|
void Renderer::applyPointsRotation(const Common::Array<BodyVertex> &vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *rotationMatrix) {
|
||||||
int32 numOfPoints2 = numPoints;
|
for (int32 i = 0; i < numPoints; ++i) {
|
||||||
|
const BodyVertex &vertex = vertices[i + firstPoint];
|
||||||
do {
|
const int32 tmpX = vertex.x;
|
||||||
const int32 tmpX = pointsPtr->x;
|
const int32 tmpY = vertex.y;
|
||||||
const int32 tmpY = pointsPtr->y;
|
const int32 tmpZ = vertex.z;
|
||||||
const int32 tmpZ = pointsPtr->z;
|
|
||||||
|
|
||||||
destPoints->x = ((rotationMatrix->row1[0] * tmpX + rotationMatrix->row1[1] * tmpY + rotationMatrix->row1[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.x;
|
destPoints->x = ((rotationMatrix->row1[0] * tmpX + rotationMatrix->row1[1] * tmpY + rotationMatrix->row1[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.x;
|
||||||
destPoints->y = ((rotationMatrix->row2[0] * tmpX + rotationMatrix->row2[1] * tmpY + rotationMatrix->row2[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.y;
|
destPoints->y = ((rotationMatrix->row2[0] * tmpX + rotationMatrix->row2[1] * tmpY + rotationMatrix->row2[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.y;
|
||||||
destPoints->z = ((rotationMatrix->row3[0] * tmpX + rotationMatrix->row3[1] * tmpY + rotationMatrix->row3[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.z;
|
destPoints->z = ((rotationMatrix->row3[0] * tmpX + rotationMatrix->row3[1] * tmpY + rotationMatrix->row3[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.z;
|
||||||
|
|
||||||
destPoints++;
|
destPoints++;
|
||||||
pointsPtr++;
|
}
|
||||||
} while (--numOfPoints2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::processRotatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *pointsPtr, int32 rotZ, int32 rotY, int32 rotX, const BonesBaseData *boneData, ModelData *modelData) {
|
void Renderer::processRotatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex> &vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData) {
|
||||||
int32 firstPoint = boneData->firstPoint / sizeof(I16Vec3);
|
const int32 firstPoint = bone.firstVertex;
|
||||||
int32 numOfPoints2 = boneData->numOfPoints;
|
const int32 numOfPoints = bone.numVertices;
|
||||||
|
|
||||||
IVec3 renderAngle;
|
IVec3 renderAngle;
|
||||||
renderAngle.x = rotX;
|
renderAngle.x = rotX;
|
||||||
|
@ -341,15 +340,15 @@ void Renderer::processRotatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *po
|
||||||
|
|
||||||
const IMatrix3x3 *currentMatrix;
|
const IMatrix3x3 *currentMatrix;
|
||||||
// if its the first point
|
// if its the first point
|
||||||
if (boneData->baseElement == -1) {
|
if (bone.isRoot()) {
|
||||||
currentMatrix = &_baseMatrix;
|
currentMatrix = &_baseMatrix;
|
||||||
|
|
||||||
destPos.x = 0;
|
destPos.x = 0;
|
||||||
destPos.y = 0;
|
destPos.y = 0;
|
||||||
destPos.z = 0;
|
destPos.z = 0;
|
||||||
} else {
|
} else {
|
||||||
const int32 pointIdx = boneData->basePoint / sizeof(I16Vec3);
|
const int32 pointIdx = bone.vertex;
|
||||||
const int32 matrixIndex = boneData->baseElement / sizeof(BonesBaseData);
|
const int32 matrixIndex = bone.parent;
|
||||||
assert(matrixIndex >= 0 && matrixIndex < ARRAYSIZE(_matricesTable));
|
assert(matrixIndex >= 0 && matrixIndex < ARRAYSIZE(_matricesTable));
|
||||||
currentMatrix = &_matricesTable[matrixIndex];
|
currentMatrix = &_matricesTable[matrixIndex];
|
||||||
|
|
||||||
|
@ -360,54 +359,52 @@ void Renderer::processRotatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *po
|
||||||
|
|
||||||
applyRotation(targetMatrix, currentMatrix, renderAngle);
|
applyRotation(targetMatrix, currentMatrix, renderAngle);
|
||||||
|
|
||||||
if (!numOfPoints2) {
|
if (!numOfPoints) {
|
||||||
warning("RENDER WARNING: No points in this model!");
|
warning("RENDER WARNING: No points in this model!");
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPointsRotation(&pointsPtr[firstPoint], numOfPoints2, &modelData->computedPoints[firstPoint], targetMatrix);
|
applyPointsRotation(vertices, firstPoint, numOfPoints, &modelData->computedPoints[firstPoint], targetMatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::applyPointsTranslation(const I16Vec3 *pointsPtr, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *translationMatrix, const IVec3 &angleVec) {
|
void Renderer::applyPointsTranslation(const Common::Array<BodyVertex> &vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *translationMatrix, const IVec3 &angleVec) {
|
||||||
int32 numOfPoints2 = numPoints;
|
for (int32 i = 0; i < numPoints; ++i) {
|
||||||
|
const BodyVertex &vertex = vertices[i + firstPoint];
|
||||||
do {
|
const int32 tmpX = vertex.x + angleVec.z;
|
||||||
const int32 tmpX = pointsPtr->x + angleVec.z;
|
const int32 tmpY = vertex.y + angleVec.y;
|
||||||
const int32 tmpY = pointsPtr->y + angleVec.y;
|
const int32 tmpZ = vertex.z + angleVec.x;
|
||||||
const int32 tmpZ = pointsPtr->z + angleVec.x;
|
|
||||||
|
|
||||||
destPoints->x = ((translationMatrix->row1[0] * tmpX + translationMatrix->row1[1] * tmpY + translationMatrix->row1[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.x;
|
destPoints->x = ((translationMatrix->row1[0] * tmpX + translationMatrix->row1[1] * tmpY + translationMatrix->row1[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.x;
|
||||||
destPoints->y = ((translationMatrix->row2[0] * tmpX + translationMatrix->row2[1] * tmpY + translationMatrix->row2[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.y;
|
destPoints->y = ((translationMatrix->row2[0] * tmpX + translationMatrix->row2[1] * tmpY + translationMatrix->row2[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.y;
|
||||||
destPoints->z = ((translationMatrix->row3[0] * tmpX + translationMatrix->row3[1] * tmpY + translationMatrix->row3[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.z;
|
destPoints->z = ((translationMatrix->row3[0] * tmpX + translationMatrix->row3[1] * tmpY + translationMatrix->row3[2] * tmpZ) / SCENE_SIZE_HALF) + destPos.z;
|
||||||
|
|
||||||
destPoints++;
|
destPoints++;
|
||||||
pointsPtr++;
|
}
|
||||||
} while (--numOfPoints2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::processTranslatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *pointsPtr, int32 rotX, int32 rotY, int32 rotZ, const BonesBaseData *boneData, ModelData *modelData) {
|
void Renderer::processTranslatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex> &vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData) {
|
||||||
IVec3 renderAngle;
|
IVec3 renderAngle;
|
||||||
renderAngle.x = rotX;
|
renderAngle.x = rotX;
|
||||||
renderAngle.y = rotY;
|
renderAngle.y = rotY;
|
||||||
renderAngle.z = rotZ;
|
renderAngle.z = rotZ;
|
||||||
|
|
||||||
if (boneData->baseElement == -1) { // base point
|
if (bone.isRoot()) { // base point
|
||||||
destPos.x = 0;
|
destPos.x = 0;
|
||||||
destPos.y = 0;
|
destPos.y = 0;
|
||||||
destPos.z = 0;
|
destPos.z = 0;
|
||||||
|
|
||||||
*targetMatrix = _baseMatrix;
|
*targetMatrix = _baseMatrix;
|
||||||
} else { // dependent
|
} else { // dependent
|
||||||
const int32 pointsIdx = boneData->basePoint / sizeof(I16Vec3);
|
const int32 pointsIdx = bone.vertex;
|
||||||
destPos.x = modelData->computedPoints[pointsIdx].x;
|
destPos.x = modelData->computedPoints[pointsIdx].x;
|
||||||
destPos.y = modelData->computedPoints[pointsIdx].y;
|
destPos.y = modelData->computedPoints[pointsIdx].y;
|
||||||
destPos.z = modelData->computedPoints[pointsIdx].z;
|
destPos.z = modelData->computedPoints[pointsIdx].z;
|
||||||
|
|
||||||
const int32 matrixIndex = boneData->baseElement / sizeof(BonesBaseData);
|
const int32 matrixIndex = bone.parent;
|
||||||
assert(matrixIndex >= 0 && matrixIndex < ARRAYSIZE(_matricesTable));
|
assert(matrixIndex >= 0 && matrixIndex < ARRAYSIZE(_matricesTable));
|
||||||
*targetMatrix = _matricesTable[matrixIndex];
|
*targetMatrix = _matricesTable[matrixIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPointsTranslation(&pointsPtr[boneData->firstPoint / sizeof(I16Vec3)], boneData->numOfPoints, &modelData->computedPoints[boneData->firstPoint / sizeof(I16Vec3)], targetMatrix, renderAngle);
|
applyPointsTranslation(vertices, bone.firstVertex, bone.numVertices, &modelData->computedPoints[bone.firstVertex], targetMatrix, renderAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::setLightVector(int32 angleX, int32 angleY, int32 angleZ) {
|
void Renderer::setLightVector(int32 angleX, int32 angleY, int32 angleZ) {
|
||||||
|
@ -1080,22 +1077,14 @@ void Renderer::circleFill(int32 x, int32 y, int32 radius, uint8 color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *Renderer::prepareSpheres(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
uint8 *Renderer::prepareSpheres(const Common::Array<BodySphere> &spheres, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
||||||
int16 numSpheres = stream.readSint16LE();
|
for (const BodySphere &sphere : spheres) {
|
||||||
if (numSpheres <= 0) {
|
CmdRenderSphere *cmd = (CmdRenderSphere *)renderBufferPtr;
|
||||||
return renderBufferPtr;
|
cmd->colorIndex = sphere.color;
|
||||||
}
|
cmd->radius = sphere.radius;
|
||||||
numOfPrimitives += numSpheres;
|
const int16 centerIndex = sphere.vertex;
|
||||||
do {
|
cmd->x = modelData->flattenPoints[centerIndex].x;
|
||||||
CmdRenderSphere *sphere = (CmdRenderSphere *)renderBufferPtr;
|
cmd->y = modelData->flattenPoints[centerIndex].y;
|
||||||
stream.skip(1);
|
|
||||||
sphere->colorIndex = stream.readByte();
|
|
||||||
stream.skip(2);
|
|
||||||
sphere->radius = stream.readUint16LE();
|
|
||||||
const int16 centerOffset = stream.readUint16LE();
|
|
||||||
const int16 centerIndex = centerOffset / 6;
|
|
||||||
sphere->x = modelData->flattenPoints[centerIndex].x;
|
|
||||||
sphere->y = modelData->flattenPoints[centerIndex].y;
|
|
||||||
|
|
||||||
(*renderCmds)->depth = modelData->flattenPoints[centerIndex].z;
|
(*renderCmds)->depth = modelData->flattenPoints[centerIndex].z;
|
||||||
(*renderCmds)->renderType = RENDERTYPE_DRAWSPHERE;
|
(*renderCmds)->renderType = RENDERTYPE_DRAWSPHERE;
|
||||||
|
@ -1103,51 +1092,38 @@ uint8 *Renderer::prepareSpheres(Common::MemoryReadStream &stream, int32 &numOfPr
|
||||||
(*renderCmds)++;
|
(*renderCmds)++;
|
||||||
|
|
||||||
renderBufferPtr += sizeof(CmdRenderSphere);
|
renderBufferPtr += sizeof(CmdRenderSphere);
|
||||||
} while (--numSpheres);
|
}
|
||||||
|
numOfPrimitives += spheres.size();
|
||||||
return renderBufferPtr;
|
return renderBufferPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *Renderer::prepareLines(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
uint8 *Renderer::prepareLines(const Common::Array<BodyLine> &lines, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
||||||
int16 numLines = stream.readSint16LE();
|
for (const BodyLine &line : lines) {
|
||||||
if (numLines <= 0) {
|
CmdRenderLine *cmd = (CmdRenderLine *)renderBufferPtr;
|
||||||
return renderBufferPtr;
|
cmd->colorIndex = line.color;
|
||||||
}
|
const int32 point1Index = line.vertex1;
|
||||||
numOfPrimitives += numLines;
|
const int32 point2Index = line.vertex2;
|
||||||
|
cmd->x1 = modelData->flattenPoints[point1Index].x;
|
||||||
do {
|
cmd->y1 = modelData->flattenPoints[point1Index].y;
|
||||||
CmdRenderLine *lineCoordinatesPtr = (CmdRenderLine *)renderBufferPtr;
|
cmd->x2 = modelData->flattenPoints[point2Index].x;
|
||||||
lineCoordinatesPtr->colorIndex = stream.readByte();
|
cmd->y2 = modelData->flattenPoints[point2Index].y;
|
||||||
stream.skip(3);
|
|
||||||
const int32 point1Index = stream.readSint16LE() / 6;
|
|
||||||
const int32 point2Index = stream.readSint16LE() / 6;
|
|
||||||
lineCoordinatesPtr->x1 = modelData->flattenPoints[point1Index].x;
|
|
||||||
lineCoordinatesPtr->y1 = modelData->flattenPoints[point1Index].y;
|
|
||||||
lineCoordinatesPtr->x2 = modelData->flattenPoints[point2Index].x;
|
|
||||||
lineCoordinatesPtr->y2 = modelData->flattenPoints[point2Index].y;
|
|
||||||
(*renderCmds)->depth = MAX(modelData->flattenPoints[point1Index].z, modelData->flattenPoints[point2Index].z);
|
(*renderCmds)->depth = MAX(modelData->flattenPoints[point1Index].z, modelData->flattenPoints[point2Index].z);
|
||||||
(*renderCmds)->renderType = RENDERTYPE_DRAWLINE;
|
(*renderCmds)->renderType = RENDERTYPE_DRAWLINE;
|
||||||
(*renderCmds)->dataPtr = renderBufferPtr;
|
(*renderCmds)->dataPtr = renderBufferPtr;
|
||||||
(*renderCmds)++;
|
(*renderCmds)++;
|
||||||
|
|
||||||
renderBufferPtr += sizeof(CmdRenderLine);
|
renderBufferPtr += sizeof(CmdRenderLine);
|
||||||
} while (--numLines);
|
}
|
||||||
|
numOfPrimitives += lines.size();
|
||||||
return renderBufferPtr;
|
return renderBufferPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
uint8 *Renderer::preparePolygons(const Common::Array<BodyPolygon> &polygons, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData) {
|
||||||
int16 numPolygons = stream.readSint16LE();
|
for (const BodyPolygon &polygon : polygons) {
|
||||||
if (numPolygons <= 0) {
|
const uint8 renderType = polygon.renderType;
|
||||||
return renderBufferPtr;
|
const uint8 numVertices = polygon.indices.size();
|
||||||
}
|
|
||||||
int16 primitiveCounter = numPolygons; // the number of primitives = the number of polygons
|
|
||||||
|
|
||||||
do { // loop that load all the polygons
|
|
||||||
const uint8 renderType = stream.readByte();
|
|
||||||
const uint8 numVertices = stream.readByte();
|
|
||||||
assert(numVertices <= 16);
|
assert(numVertices <= 16);
|
||||||
const int16 colorIndex = stream.readSint16LE();
|
const int16 colorIndex = polygon.color;
|
||||||
|
|
||||||
int16 bestDepth = -32000;
|
int16 bestDepth = -32000;
|
||||||
|
|
||||||
|
@ -1160,19 +1136,16 @@ uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfP
|
||||||
renderBufferPtr += destinationPolygon->numVertices * sizeof(Vertex);
|
renderBufferPtr += destinationPolygon->numVertices * sizeof(Vertex);
|
||||||
|
|
||||||
Vertex *vertex = vertices;
|
Vertex *vertex = vertices;
|
||||||
int16 counter = destinationPolygon->numVertices;
|
|
||||||
|
|
||||||
// TODO: RECHECK coordinates axis
|
// TODO: RECHECK coordinates axis
|
||||||
if (renderType >= 9) {
|
if (renderType >= POLYGONTYPE_UNKNOWN) {
|
||||||
destinationPolygon->renderType = renderType - 2;
|
destinationPolygon->renderType = polygon.renderType - 2;
|
||||||
destinationPolygon->colorIndex = colorIndex;
|
destinationPolygon->colorIndex = polygon.color;
|
||||||
|
|
||||||
do {
|
for (int16 idx = 0; idx < numVertices; ++idx) {
|
||||||
const int16 shadeEntry = stream.readSint16LE();
|
const int16 shadeEntry = polygon.intensities[idx];
|
||||||
const int16 shadeValue = colorIndex + modelData->shadeTable[shadeEntry];
|
const int16 shadeValue = colorIndex + modelData->shadeTable[shadeEntry];
|
||||||
|
const int16 vertexIndex = polygon.indices[idx];
|
||||||
const int16 vertexOffset = stream.readSint16LE();
|
|
||||||
const int16 vertexIndex = vertexOffset / 6;
|
|
||||||
const I16Vec3 *point = &modelData->flattenPoints[vertexIndex];
|
const I16Vec3 *point = &modelData->flattenPoints[vertexIndex];
|
||||||
|
|
||||||
vertex->colorIndex = shadeValue;
|
vertex->colorIndex = shadeValue;
|
||||||
|
@ -1180,12 +1153,12 @@ uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfP
|
||||||
vertex->y = point->y;
|
vertex->y = point->y;
|
||||||
bestDepth = MAX(bestDepth, point->z);
|
bestDepth = MAX(bestDepth, point->z);
|
||||||
++vertex;
|
++vertex;
|
||||||
} while (--counter > 0);
|
}
|
||||||
} else {
|
} else {
|
||||||
if (renderType >= POLYGONTYPE_GOURAUD) {
|
if (renderType >= POLYGONTYPE_GOURAUD) {
|
||||||
// only 1 shade value is used
|
// only 1 shade value is used
|
||||||
destinationPolygon->renderType = renderType - POLYGONTYPE_GOURAUD;
|
destinationPolygon->renderType = renderType - POLYGONTYPE_GOURAUD;
|
||||||
const int16 shadeEntry = stream.readSint16LE();
|
const int16 shadeEntry = polygon.intensities[0];
|
||||||
const int16 shadeValue = colorIndex + modelData->shadeTable[shadeEntry];
|
const int16 shadeValue = colorIndex + modelData->shadeTable[shadeEntry];
|
||||||
destinationPolygon->colorIndex = shadeValue;
|
destinationPolygon->colorIndex = shadeValue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1194,9 +1167,8 @@ uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfP
|
||||||
destinationPolygon->colorIndex = colorIndex;
|
destinationPolygon->colorIndex = colorIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
for (int16 idx = 0; idx < numVertices; ++idx) {
|
||||||
const int16 vertexOffset = stream.readSint16LE();
|
const int16 vertexIndex = polygon.indices[idx];
|
||||||
const int16 vertexIndex = vertexOffset / 6;
|
|
||||||
const I16Vec3 *point = &modelData->flattenPoints[vertexIndex];
|
const I16Vec3 *point = &modelData->flattenPoints[vertexIndex];
|
||||||
|
|
||||||
vertex->colorIndex = destinationPolygon->colorIndex;
|
vertex->colorIndex = destinationPolygon->colorIndex;
|
||||||
|
@ -1204,7 +1176,7 @@ uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfP
|
||||||
vertex->y = point->y;
|
vertex->y = point->y;
|
||||||
bestDepth = MAX(bestDepth, point->z);
|
bestDepth = MAX(bestDepth, point->z);
|
||||||
++vertex;
|
++vertex;
|
||||||
} while (--counter > 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
numOfPrimitives++;
|
numOfPrimitives++;
|
||||||
|
@ -1213,7 +1185,7 @@ uint8 *Renderer::preparePolygons(Common::MemoryReadStream &stream, int32 &numOfP
|
||||||
(*renderCmds)->renderType = RENDERTYPE_DRAWPOLYGON;
|
(*renderCmds)->renderType = RENDERTYPE_DRAWPOLYGON;
|
||||||
(*renderCmds)->dataPtr = (uint8 *)destinationPolygon;
|
(*renderCmds)->dataPtr = (uint8 *)destinationPolygon;
|
||||||
(*renderCmds)++;
|
(*renderCmds)++;
|
||||||
} while (--primitiveCounter);
|
}
|
||||||
|
|
||||||
return renderBufferPtr;
|
return renderBufferPtr;
|
||||||
}
|
}
|
||||||
|
@ -1223,14 +1195,11 @@ const Renderer::RenderCommand *Renderer::depthSortRenderCommands(int32 numOfPrim
|
||||||
return _renderCmds;
|
return _renderCmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::renderModelElements(int32 numOfPrimitives, const uint8 *polygonPtr, RenderCommand **renderCmds, ModelData *modelData) {
|
bool Renderer::renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData) {
|
||||||
// TODO: proper size
|
|
||||||
Common::MemoryReadStream stream(polygonPtr, 100000);
|
|
||||||
|
|
||||||
uint8 *renderBufferPtr = _renderCoordinatesBuffer;
|
uint8 *renderBufferPtr = _renderCoordinatesBuffer;
|
||||||
renderBufferPtr = preparePolygons(stream, numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
renderBufferPtr = preparePolygons(bodyData.getPolygons(), numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
||||||
renderBufferPtr = prepareLines(stream, numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
renderBufferPtr = prepareLines(bodyData.getLines(), numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
||||||
renderBufferPtr = prepareSpheres(stream, numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
renderBufferPtr = prepareSpheres(bodyData.getSpheres(), numOfPrimitives, renderCmds, renderBufferPtr, modelData);
|
||||||
|
|
||||||
if (numOfPrimitives == 0) {
|
if (numOfPrimitives == 0) {
|
||||||
_engine->_redraw->renderRect.right = -1;
|
_engine->_redraw->renderRect.right = -1;
|
||||||
|
@ -1305,32 +1274,32 @@ bool Renderer::renderModelElements(int32 numOfPrimitives, const uint8 *polygonPt
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos) {
|
bool Renderer::renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos) {
|
||||||
const int32 numVertices = Model::getNumVertices(bodyPtr);
|
const int32 numVertices = bodyData.getNumVertices();
|
||||||
const int32 numBones = Model::getNumBones(bodyPtr);
|
const int32 numBones = bodyData.getNumBones();
|
||||||
|
|
||||||
const I16Vec3 *pointsPtr = Model::getVerticesBaseData(bodyPtr);
|
const Common::Array<BodyVertex> &vertices = bodyData.getVertices();
|
||||||
|
|
||||||
IMatrix3x3 *modelMatrix = &_matricesTable[0];
|
IMatrix3x3 *modelMatrix = &_matricesTable[0];
|
||||||
|
|
||||||
const BonesBaseData *boneData = Model::getBonesBaseData(bodyPtr, 0);
|
const BodyBone &firstBone = bodyData.getBone(0);
|
||||||
processRotatedElement(modelMatrix, pointsPtr, angleVec.x, angleVec.y, angleVec.z, boneData, modelData);
|
processRotatedElement(modelMatrix, vertices, angleVec.x, angleVec.y, angleVec.z, firstBone, modelData);
|
||||||
|
|
||||||
int32 numOfPrimitives = 0;
|
int32 numOfPrimitives = 0;
|
||||||
|
|
||||||
if (numBones - 1 != 0) {
|
if (numBones - 1 != 0) {
|
||||||
numOfPrimitives = numBones - 1;
|
numOfPrimitives = numBones - 1;
|
||||||
modelMatrix = &_matricesTable[1];
|
|
||||||
|
|
||||||
int boneIdx = 1;
|
int boneIdx = 1;
|
||||||
do {
|
modelMatrix = &_matricesTable[boneIdx];
|
||||||
boneData = Model::getBonesBaseData(bodyPtr, boneIdx);
|
|
||||||
int16 boneType = boneData->flag;
|
|
||||||
|
|
||||||
if (boneType == 0) {
|
do {
|
||||||
processRotatedElement(modelMatrix, pointsPtr, boneData->rotateX, boneData->rotateY, boneData->rotateZ, boneData, modelData);
|
const BodyBone &bone = bodyData.getBone(boneIdx);
|
||||||
} else if (boneType == 1) {
|
const BoneFrame *boneData = bodyData.getBoneState(boneIdx);
|
||||||
processTranslatedElement(modelMatrix, pointsPtr, boneData->rotateX, boneData->rotateY, boneData->rotateZ, boneData, modelData);
|
|
||||||
|
if (boneData->type == 0) {
|
||||||
|
processRotatedElement(modelMatrix, vertices, boneData->x, boneData->y, boneData->z, bone, modelData);
|
||||||
|
} else if (boneData->type == 1) {
|
||||||
|
processTranslatedElement(modelMatrix, vertices, boneData->x, boneData->y, boneData->z, bone, modelData);
|
||||||
}
|
}
|
||||||
|
|
||||||
++modelMatrix;
|
++modelMatrix;
|
||||||
|
@ -1432,7 +1401,7 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, R
|
||||||
} while (--numOfPrimitives);
|
} while (--numOfPrimitives);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 numOfShades = Model::getNumShades(bodyPtr);
|
int32 numOfShades = bodyData.getShades().size();
|
||||||
|
|
||||||
if (numOfShades) { // process normal data
|
if (numOfShades) { // process normal data
|
||||||
uint16 *currentShadeDestination = (uint16 *)modelData->shadeTable;
|
uint16 *currentShadeDestination = (uint16 *)modelData->shadeTable;
|
||||||
|
@ -1443,7 +1412,7 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, R
|
||||||
int shadeIndex = 0;
|
int shadeIndex = 0;
|
||||||
int boneIdx = 0;
|
int boneIdx = 0;
|
||||||
do { // for each element
|
do { // for each element
|
||||||
numOfShades = Model::getNumShadesBone(bodyPtr, boneIdx);
|
numOfShades = bodyData.getBone(boneIdx).numOfShades;
|
||||||
|
|
||||||
if (numOfShades) {
|
if (numOfShades) {
|
||||||
int32 numShades = numOfShades;
|
int32 numShades = numOfShades;
|
||||||
|
@ -1451,11 +1420,11 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, R
|
||||||
_shadeMatrix = *lightMatrix * _lightPos;
|
_shadeMatrix = *lightMatrix * _lightPos;
|
||||||
|
|
||||||
do { // for each normal
|
do { // for each normal
|
||||||
const BodyShade *shadePtr = Model::getBodyShadesData(bodyPtr, shadeIndex);
|
const BodyShade &shadePtr = bodyData.getShade(shadeIndex);
|
||||||
|
|
||||||
const int16 col1 = shadePtr->col1;
|
const int16 col1 = shadePtr.col1;
|
||||||
const int16 col2 = shadePtr->col2;
|
const int16 col2 = shadePtr.col2;
|
||||||
const int16 col3 = shadePtr->col3;
|
const int16 col3 = shadePtr.col3;
|
||||||
|
|
||||||
int32 color = 0;
|
int32 color = 0;
|
||||||
color += _shadeMatrix.row1[0] * col1 + _shadeMatrix.row1[1] * col2 + _shadeMatrix.row1[2] * col3;
|
color += _shadeMatrix.row1[0] * col1 + _shadeMatrix.row1[1] * col2 + _shadeMatrix.row1[2] * col3;
|
||||||
|
@ -1466,7 +1435,7 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, R
|
||||||
|
|
||||||
if (color > 0) {
|
if (color > 0) {
|
||||||
color >>= 14;
|
color >>= 14;
|
||||||
color /= shadePtr->unk4;
|
color /= shadePtr.unk4;
|
||||||
shade = (uint16)color;
|
shade = (uint16)color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1481,10 +1450,10 @@ bool Renderer::renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, R
|
||||||
} while (--numOfPrimitives);
|
} while (--numOfPrimitives);
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderModelElements(numOfPrimitives, Model::getPolygonData(bodyPtr), &renderCmds, modelData);
|
return renderModelElements(numOfPrimitives, bodyData, &renderCmds, modelData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Renderer::renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const uint8 *bodyPtr) {
|
bool Renderer::renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const BodyData &bodyData) {
|
||||||
IVec3 renderAngle;
|
IVec3 renderAngle;
|
||||||
renderAngle.x = angleX;
|
renderAngle.x = angleX;
|
||||||
renderAngle.y = angleY;
|
renderAngle.y = angleY;
|
||||||
|
@ -1507,18 +1476,18 @@ bool Renderer::renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 ang
|
||||||
renderPos = destPos - baseRotPos; // RECHECK y
|
renderPos = destPos - baseRotPos; // RECHECK y
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Model::isAnimated(bodyPtr)) {
|
if (!bodyData.isAnimated()) {
|
||||||
error("Unsupported unanimated model render!");
|
error("Unsupported unanimated model render!");
|
||||||
}
|
}
|
||||||
// restart at the beginning of the renderTable
|
// restart at the beginning of the renderTable
|
||||||
return renderAnimatedModel(&_modelData, bodyPtr, _renderCmds, renderAngle, renderPos);
|
return renderAnimatedModel(&_modelData, bodyData, _renderCmds, renderAngle, renderPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const uint8 *bodyPtr) {
|
void Renderer::renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const BodyData &bodyData) {
|
||||||
renderBehaviourModel(rect.left, rect.top, rect.right, rect.bottom, y, angle, bodyPtr);
|
renderBehaviourModel(rect.left, rect.top, rect.right, rect.bottom, y, angle, bodyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const uint8 *bodyPtr) {
|
void Renderer::renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const BodyData &bodyData) {
|
||||||
const int32 ypos = (boxBottom + boxTop) / 2;
|
const int32 ypos = (boxBottom + boxTop) / 2;
|
||||||
const int32 xpos = (boxRight + boxLeft) / 2;
|
const int32 xpos = (boxRight + boxLeft) / 2;
|
||||||
|
|
||||||
|
@ -1531,17 +1500,17 @@ void Renderer::renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight,
|
||||||
if (move.numOfStep == 0) {
|
if (move.numOfStep == 0) {
|
||||||
_engine->_movements->setActorAngleSafe(newAngle, newAngle - ANGLE_90, ANGLE_17, &move);
|
_engine->_movements->setActorAngleSafe(newAngle, newAngle - ANGLE_90, ANGLE_17, &move);
|
||||||
}
|
}
|
||||||
renderIsoModel(0, y, 0, ANGLE_0, newAngle, ANGLE_0, bodyPtr);
|
renderIsoModel(0, y, 0, ANGLE_0, newAngle, ANGLE_0, bodyData);
|
||||||
} else {
|
} else {
|
||||||
renderIsoModel(0, y, 0, ANGLE_0, angle, ANGLE_0, bodyPtr);
|
renderIsoModel(0, y, 0, ANGLE_0, angle, ANGLE_0, bodyData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderInventoryItem(int32 x, int32 y, const uint8 *bodyPtr, int32 angle, int32 param) {
|
void Renderer::renderInventoryItem(int32 x, int32 y, const BodyData &bodyData, int32 angle, int32 param) {
|
||||||
setCameraPosition(x, y, 128, 200, 200);
|
setCameraPosition(x, y, 128, 200, 200);
|
||||||
setCameraAngle(0, 0, 0, 60, 0, 0, param);
|
setCameraAngle(0, 0, 0, 60, 0, 0, param);
|
||||||
|
|
||||||
renderIsoModel(0, 0, 0, ANGLE_0, angle, ANGLE_0, bodyPtr);
|
renderIsoModel(0, 0, 0, ANGLE_0, angle, ANGLE_0, bodyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::computeHolomapPolygon(int32 top, int32 x1, int32 bottom, int32 x2, int16 *polygonTabPtr) {
|
void Renderer::computeHolomapPolygon(int32 top, int32 x1, int32 bottom, int32 x2, int16 *polygonTabPtr) {
|
||||||
|
|
|
@ -83,122 +83,6 @@ inline IMatrix3x3 operator*(const IMatrix3x3 &matrix, const IVec3 &vec) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "common/pack-start.h"
|
|
||||||
struct BonesBaseData {
|
|
||||||
int16 firstPoint = 0; // data1
|
|
||||||
int16 numOfPoints = 0; // data2
|
|
||||||
int16 basePoint = 0; // data3
|
|
||||||
int16 baseElement = 0; // param
|
|
||||||
int16 flag = 0;
|
|
||||||
int16 rotateZ = 0;
|
|
||||||
int16 rotateY = 0;
|
|
||||||
int16 rotateX = 0;
|
|
||||||
int16 unk1 = 0; // field_10
|
|
||||||
int16 numOfShades = 0;
|
|
||||||
int16 unk2 = 0;
|
|
||||||
int32 field_18 = 0;
|
|
||||||
int32 y = 0;
|
|
||||||
int32 field_20 = 0;
|
|
||||||
int32 field_24 = 0;
|
|
||||||
};
|
|
||||||
#include "common/pack-end.h"
|
|
||||||
static_assert(sizeof(BonesBaseData) == 38, "Unexpected elementEntry size");
|
|
||||||
|
|
||||||
class Model {
|
|
||||||
private:
|
|
||||||
static uint8 *getBonesData(uint8 *bodyPtr) {
|
|
||||||
uint8 *verticesBase = getData(bodyPtr);
|
|
||||||
const int16 numVertices = READ_LE_INT16(verticesBase);
|
|
||||||
return verticesBase + 2 + numVertices * sizeof(I16Vec3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8 *getBonesData(const uint8 *bodyPtr) {
|
|
||||||
const uint8 *verticesBase = getData(bodyPtr);
|
|
||||||
const int16 numVertices = READ_LE_INT16(verticesBase);
|
|
||||||
return verticesBase + 2 + numVertices * sizeof(I16Vec3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8 *getData(uint8 *bodyPtr) {
|
|
||||||
return bodyPtr + 0x1A;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8 *getData(const uint8 *bodyPtr) {
|
|
||||||
return bodyPtr + 0x1A;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BonesBaseData *getBonesBaseData(uint8 *bodyPtr, int boneIdx = 0) {
|
|
||||||
assert(boneIdx <= getNumBones(bodyPtr));
|
|
||||||
return (BonesBaseData *)(getBonesData(bodyPtr) + 2 + (boneIdx * sizeof(BonesBaseData)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8 *getShadesData(const uint8 *bodyPtr) {
|
|
||||||
const int16 numBones = getNumBones(bodyPtr);
|
|
||||||
return (const uint8 *)getBonesBaseData(bodyPtr, numBones);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
static inline bool isAnimated(const uint8 *bodyPtr) {
|
|
||||||
const int16 bodyHeader = READ_LE_INT16(bodyPtr);
|
|
||||||
return (bodyHeader & 2) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const I16Vec3 *getVerticesBaseData(const uint8 *bodyPtr) {
|
|
||||||
return (const I16Vec3*)(getData(bodyPtr) + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const BoneFrame *getBonesStateData(const uint8 *bodyPtr, int boneIdx) {
|
|
||||||
assert(boneIdx <= getNumBones(bodyPtr));
|
|
||||||
return (const BoneFrame*)((const uint8*)getBonesBaseData(bodyPtr) + 8 + (boneIdx * sizeof(BonesBaseData)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static BoneFrame *getBonesStateData(uint8 *bodyPtr, int boneIdx) {
|
|
||||||
assert(boneIdx <= getNumBones(bodyPtr));
|
|
||||||
return (BoneFrame*)((uint8*)getBonesBaseData(bodyPtr) + 8 + (boneIdx * sizeof(BonesBaseData)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const BonesBaseData *getBonesBaseData(const uint8 *bodyPtr, int boneIdx = 0) {
|
|
||||||
assert(boneIdx <= getNumBones(bodyPtr));
|
|
||||||
return (const BonesBaseData *)(getBonesData(bodyPtr) + 2 + (boneIdx * sizeof(BonesBaseData)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int16 getNumBones(const uint8 *bodyPtr) {
|
|
||||||
const uint8 *bonesBase = getBonesData(bodyPtr);
|
|
||||||
return READ_LE_INT16(bonesBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int16 getNumVertices(const uint8 *bodyPtr) {
|
|
||||||
const uint8 *verticesBase = getData(bodyPtr);
|
|
||||||
return READ_LE_INT16(verticesBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const BodyShade *getBodyShadesData(const uint8 *bodyPtr, int16 shadeIdx = 0) {
|
|
||||||
assert(shadeIdx <= getNumShades(bodyPtr));
|
|
||||||
return (const BodyShade*)(getShadesData(bodyPtr) + 2 + (shadeIdx * sizeof(BodyShade)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int16 getNumShades(const uint8 *bodyPtr) {
|
|
||||||
const uint8 *shadesBase = getShadesData(bodyPtr);
|
|
||||||
return READ_LE_INT16(shadesBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int16 getNumShadesBone(const uint8 *bodyPtr, int boneIdx) {
|
|
||||||
return getBonesBaseData(bodyPtr, boneIdx)->numOfShades;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8 *getPolygonData(const uint8 *bodyPtr) {
|
|
||||||
const uint8 *shades = (const uint8*)getBodyShadesData(bodyPtr);
|
|
||||||
const int16 numShades = getNumShades(bodyPtr);
|
|
||||||
if (numShades <= 0) {
|
|
||||||
return shades;
|
|
||||||
}
|
|
||||||
const int16 bones = getNumBones(bodyPtr);
|
|
||||||
for (int16 boneIdx = 0; boneIdx < bones; ++boneIdx) {
|
|
||||||
int16 numOfShades = getNumShadesBone(bodyPtr, boneIdx);
|
|
||||||
shades += numOfShades * 8;
|
|
||||||
}
|
|
||||||
return shades;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
private:
|
private:
|
||||||
TwinEEngine *_engine;
|
TwinEEngine *_engine;
|
||||||
|
@ -254,15 +138,15 @@ private:
|
||||||
|
|
||||||
ModelData _modelData;
|
ModelData _modelData;
|
||||||
|
|
||||||
bool renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos);
|
bool renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos);
|
||||||
void circleFill(int32 x, int32 y, int32 radius, uint8 color);
|
void circleFill(int32 x, int32 y, int32 radius, uint8 color);
|
||||||
bool renderModelElements(int32 numOfPrimitives, const uint8 *polygonPtr, RenderCommand **renderCmds, ModelData *modelData);
|
bool renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData);
|
||||||
void getCameraAnglePositions(int32 x, int32 y, int32 z);
|
void getCameraAnglePositions(int32 x, int32 y, int32 z);
|
||||||
void applyRotation(IMatrix3x3 *targetMatrix, const IMatrix3x3 *currentMatrix, const IVec3 &angleVec);
|
void applyRotation(IMatrix3x3 *targetMatrix, const IMatrix3x3 *currentMatrix, const IVec3 &angleVec);
|
||||||
void applyPointsRotation(const I16Vec3 *pointsPtr, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *rotationMatrix);
|
void applyPointsRotation(const Common::Array<BodyVertex>& vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *rotationMatrix);
|
||||||
void processRotatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *pointsPtr, int32 rotZ, int32 rotY, int32 rotX, const BonesBaseData *boneData, ModelData *modelData);
|
void processRotatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex>& vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData);
|
||||||
void applyPointsTranslation(const I16Vec3 *pointsPtr, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *translationMatrix, const IVec3 &angleVec);
|
void applyPointsTranslation(const Common::Array<BodyVertex>& vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *translationMatrix, const IVec3 &angleVec);
|
||||||
void processTranslatedElement(IMatrix3x3 *targetMatrix, const I16Vec3 *pointsPtr, int32 rotX, int32 rotY, int32 rotZ, const BonesBaseData *boneData, ModelData *modelData);
|
void processTranslatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex>& vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData);
|
||||||
void translateGroup(int32 x, int32 y, int32 z);
|
void translateGroup(int32 x, int32 y, int32 z);
|
||||||
|
|
||||||
IVec3 _baseTransPos;
|
IVec3 _baseTransPos;
|
||||||
|
@ -312,9 +196,9 @@ private:
|
||||||
void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
|
void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
|
||||||
|
|
||||||
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
|
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
|
||||||
uint8 *preparePolygons(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
uint8 *preparePolygons(const Common::Array<BodyPolygon>& polygons, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
||||||
uint8 *prepareSpheres(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
uint8 *prepareSpheres(const Common::Array<BodySphere>& spheres, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
||||||
uint8 *prepareLines(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
uint8 *prepareLines(const Common::Array<BodyLine>& lines, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
||||||
|
|
||||||
void baseMatrixTranspose();
|
void baseMatrixTranspose();
|
||||||
|
|
||||||
|
@ -355,18 +239,18 @@ public:
|
||||||
void setBaseRotation(int32 x, int32 y, int32 z, bool transpose = false);
|
void setBaseRotation(int32 x, int32 y, int32 z, bool transpose = false);
|
||||||
void setOrthoProjection(int32 x, int32 y, int32 z);
|
void setOrthoProjection(int32 x, int32 y, int32 z);
|
||||||
|
|
||||||
bool renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const uint8 *bodyPtr);
|
bool renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const BodyData &bodyData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param angle A value of @c -1 means that the model is automatically rotated
|
* @param angle A value of @c -1 means that the model is automatically rotated
|
||||||
*/
|
*/
|
||||||
void renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const uint8 *bodyPtr);
|
void renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const BodyData &bodyData);
|
||||||
/**
|
/**
|
||||||
* @param angle A value of @c -1 means that the model is automatically rotated
|
* @param angle A value of @c -1 means that the model is automatically rotated
|
||||||
*/
|
*/
|
||||||
void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const uint8 *bodyPtr);
|
void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const BodyData &bodyData);
|
||||||
|
|
||||||
void renderInventoryItem(int32 x, int32 y, const uint8 *bodyPtr, int32 angle, int32 param);
|
void renderInventoryItem(int32 x, int32 y, const BodyData &bodyData, int32 angle, int32 param);
|
||||||
|
|
||||||
void renderHolomapVertices(const Vertex vertexCoordinates[3], const Vertex vertexAngles[3]);
|
void renderHolomapVertices(const Vertex vertexCoordinates[3], const Vertex vertexAngles[3]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,26 +34,16 @@
|
||||||
namespace TwinE {
|
namespace TwinE {
|
||||||
|
|
||||||
Resources::~Resources() {
|
Resources::~Resources() {
|
||||||
for (size_t i = 0; i < ARRAYSIZE(inventoryTable); ++i) {
|
|
||||||
free(inventoryTable[i]);
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < ARRAYSIZE(spriteTable); ++i) {
|
for (size_t i = 0; i < ARRAYSIZE(spriteTable); ++i) {
|
||||||
free(spriteTable[i]);
|
free(spriteTable[i]);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < ARRAYSIZE(samplesTable); ++i) {
|
for (size_t i = 0; i < ARRAYSIZE(samplesTable); ++i) {
|
||||||
free(samplesTable[i]);
|
free(samplesTable[i]);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < ARRAYSIZE(bodyTable); ++i) {
|
|
||||||
free(bodyTable[i]);
|
|
||||||
}
|
|
||||||
free(fontPtr);
|
free(fontPtr);
|
||||||
free(spriteShadowPtr);
|
free(spriteShadowPtr);
|
||||||
free(holomapSurfacePtr);
|
free(holomapSurfacePtr);
|
||||||
free(holomapImagePtr);
|
free(holomapImagePtr);
|
||||||
free(holomapTwinsenModelPtr);
|
|
||||||
free(holomapPointModelPtr);
|
|
||||||
free(holomapTwinsenArrowPtr);
|
|
||||||
free(holomapArrowPtr);
|
|
||||||
free(_engine->_screens->mainPalette);
|
free(_engine->_screens->mainPalette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +132,7 @@ void Resources::preloadInventoryItems() {
|
||||||
}
|
}
|
||||||
debug("preload %i inventory items", numEntries);
|
debug("preload %i inventory items", numEntries);
|
||||||
for (int32 i = 0; i < numEntries; i++) {
|
for (int32 i = 0; i < numEntries; i++) {
|
||||||
inventorySizeTable[i] = HQR::getAllocEntry(&inventoryTable[i], Resources::HQR_INVOBJ_FILE, i);
|
inventoryTable[i].loadFromHQR(Resources::HQR_INVOBJ_FILE, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,23 +169,19 @@ void Resources::initResources() {
|
||||||
error("Failed to load holomap image");
|
error("Failed to load holomap image");
|
||||||
}
|
}
|
||||||
|
|
||||||
holomapTwinsenModelSize = HQR::getAllocEntry(&holomapTwinsenModelPtr, Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINMDL);
|
if (!holomapTwinsenModelPtr.loadFromHQR(Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINMDL)) {
|
||||||
if (holomapTwinsenModelSize == 0) {
|
|
||||||
error("Failed to load holomap twinsen model");
|
error("Failed to load holomap twinsen model");
|
||||||
}
|
}
|
||||||
|
|
||||||
holomapPointModelSize = HQR::getAllocEntry(&holomapPointModelPtr, Resources::HQR_RESS_FILE, RESSHQR_HOLOPOINTMDL);
|
if (!holomapPointModelPtr.loadFromHQR(Resources::HQR_RESS_FILE, RESSHQR_HOLOPOINTMDL)) {
|
||||||
if (holomapPointModelSize == 0) {
|
|
||||||
error("Failed to load holomap point model");
|
error("Failed to load holomap point model");
|
||||||
}
|
}
|
||||||
|
|
||||||
holomapArrowSize = HQR::getAllocEntry(&holomapArrowPtr, Resources::HQR_RESS_FILE, RESSHQR_HOLOARROWMDL);
|
if (!holomapArrowPtr.loadFromHQR(Resources::HQR_RESS_FILE, RESSHQR_HOLOARROWMDL)) {
|
||||||
if (holomapArrowSize == 0) {
|
|
||||||
error("Failed to load holomap arrow model");
|
error("Failed to load holomap arrow model");
|
||||||
}
|
}
|
||||||
|
|
||||||
holomapTwinsenArrowSize = HQR::getAllocEntry(&holomapTwinsenArrowPtr, Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINARROWMDL);
|
if (!holomapTwinsenArrowPtr.loadFromHQR(Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINARROWMDL)) {
|
||||||
if (holomapTwinsenArrowSize == 0) {
|
|
||||||
error("Failed to load holomap twinsen arrow model");
|
error("Failed to load holomap twinsen arrow model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,7 @@ public:
|
||||||
const Common::Array<int32>& getFlaMovieInfo(const Common::String &name) const;
|
const Common::Array<int32>& getFlaMovieInfo(const Common::String &name) const;
|
||||||
|
|
||||||
/** Table with all loaded samples */
|
/** Table with all loaded samples */
|
||||||
uint8 *inventoryTable[NUM_INVENTORY_ITEMS] {nullptr};
|
BodyData inventoryTable[NUM_INVENTORY_ITEMS];
|
||||||
/** Table with all loaded samples sizes */
|
|
||||||
uint32 inventorySizeTable[NUM_INVENTORY_ITEMS] {0};
|
|
||||||
|
|
||||||
/** Table with all loaded sprites */
|
/** Table with all loaded sprites */
|
||||||
uint8 *spriteTable[NUM_SPRITES] {nullptr};
|
uint8 *spriteTable[NUM_SPRITES] {nullptr};
|
||||||
|
@ -173,8 +171,6 @@ public:
|
||||||
AnimData animData[NUM_ANIMS];
|
AnimData animData[NUM_ANIMS];
|
||||||
|
|
||||||
/** Actors 3D body table - size of NUM_BODIES */
|
/** Actors 3D body table - size of NUM_BODIES */
|
||||||
uint8 *bodyTable[NUM_BODIES]{nullptr};
|
|
||||||
int32 bodyTableSize[NUM_BODIES]{0};
|
|
||||||
BodyData bodyData[NUM_BODIES];
|
BodyData bodyData[NUM_BODIES];
|
||||||
|
|
||||||
/** Table with all loaded samples */
|
/** Table with all loaded samples */
|
||||||
|
@ -194,14 +190,11 @@ public:
|
||||||
uint8 *holomapSurfacePtr = nullptr;
|
uint8 *holomapSurfacePtr = nullptr;
|
||||||
uint32 holomapImageSize = 0;
|
uint32 holomapImageSize = 0;
|
||||||
uint8 *holomapImagePtr = nullptr;
|
uint8 *holomapImagePtr = nullptr;
|
||||||
uint32 holomapPointModelSize = 0;
|
|
||||||
uint8 *holomapPointModelPtr = nullptr;
|
BodyData holomapPointModelPtr;
|
||||||
uint32 holomapTwinsenModelSize = 0;
|
BodyData holomapTwinsenModelPtr;
|
||||||
uint8 *holomapTwinsenModelPtr = nullptr;
|
BodyData holomapTwinsenArrowPtr;
|
||||||
uint32 holomapTwinsenArrowSize = 0;
|
BodyData holomapArrowPtr;
|
||||||
uint8 *holomapTwinsenArrowPtr = nullptr;
|
|
||||||
uint32 holomapArrowSize = 0;
|
|
||||||
uint8 *holomapArrowPtr = nullptr;
|
|
||||||
|
|
||||||
/** Initialize resource pointers */
|
/** Initialize resource pointers */
|
||||||
void initResources();
|
void initResources();
|
||||||
|
|
|
@ -188,11 +188,7 @@ int32 Actor::initBody(BodyType bodyIdx, int32 actorIdx, ActorBoundingBox &actorB
|
||||||
if (!(bodyIndex & 0x8000)) {
|
if (!(bodyIndex & 0x8000)) {
|
||||||
index = _currentPositionInBodyPtrTab;
|
index = _currentPositionInBodyPtrTab;
|
||||||
_currentPositionInBodyPtrTab++;
|
_currentPositionInBodyPtrTab++;
|
||||||
_engine->_resources->bodyTableSize[index] = HQR::getAllocEntry(&_engine->_resources->bodyTable[index], Resources::HQR_BODY_FILE, bodyIndex & 0xFFFF);
|
if (!_engine->_resources->bodyData[index].loadFromHQR(Resources::HQR_BODY_FILE, bodyIndex & 0xFFFF)) {
|
||||||
if (_engine->_resources->bodyTableSize[index] == 0) {
|
|
||||||
error("HQR ERROR: Loading body entity for actor %i: %i", actorIdx, (int)bodyIdx);
|
|
||||||
}
|
|
||||||
if (!_engine->_resources->bodyData[index].loadFromBuffer(_engine->_resources->bodyTable[index], _engine->_resources->bodyTableSize[index])) {
|
|
||||||
error("HQR ERROR: Parsing body entity for actor %i: %i", actorIdx, (int)bodyIdx);
|
error("HQR ERROR: Parsing body entity for actor %i: %i", actorIdx, (int)bodyIdx);
|
||||||
}
|
}
|
||||||
stream.seek(stream.pos() - sizeof(uint16));
|
stream.seek(stream.pos() - sizeof(uint16));
|
||||||
|
|
|
@ -101,8 +101,8 @@ int16 Animations::applyAnimStepTranslation(int32 deltaTime, int32 keyFrameLength
|
||||||
return computedPos;
|
return computedPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData, uint8 *const bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
|
bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData, BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr) {
|
||||||
if (!Model::isAnimated(bodyPtr)) {
|
if (!bodyData.isAnimated()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const KeyFrame *keyFrame = animData.getKeyframe(keyframeIdx);
|
const KeyFrame *keyFrame = animData.getKeyframe(keyframeIdx);
|
||||||
|
@ -114,7 +114,7 @@ bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData,
|
||||||
processRotationByAnim = keyFrame->boneframes[0].type;
|
processRotationByAnim = keyFrame->boneframes[0].type;
|
||||||
processLastRotationAngle = ToAngle(keyFrame->boneframes[0].y);
|
processLastRotationAngle = ToAngle(keyFrame->boneframes[0].y);
|
||||||
|
|
||||||
const int16 numBones = Model::getNumBones(bodyPtr);
|
const int16 numBones = bodyData.getNumBones();
|
||||||
|
|
||||||
int32 numOfBonesInAnim = animData.getNumBoneframes();
|
int32 numOfBonesInAnim = animData.getNumBoneframes();
|
||||||
if (numOfBonesInAnim > numBones) {
|
if (numOfBonesInAnim > numBones) {
|
||||||
|
@ -130,7 +130,7 @@ bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData,
|
||||||
}
|
}
|
||||||
const int32 deltaTime = _engine->lbaTime - remainingFrameTime;
|
const int32 deltaTime = _engine->lbaTime - remainingFrameTime;
|
||||||
if (deltaTime >= keyFrameLength) {
|
if (deltaTime >= keyFrameLength) {
|
||||||
copyKeyFrameToState(keyFrame, bodyPtr, numOfBonesInAnim);
|
copyKeyFrameToState(keyFrame, bodyData, numOfBonesInAnim);
|
||||||
animTimerDataPtr->ptr = keyFrame;
|
animTimerDataPtr->ptr = keyFrame;
|
||||||
animTimerDataPtr->time = _engine->lbaTime;
|
animTimerDataPtr->time = _engine->lbaTime;
|
||||||
return true;
|
return true;
|
||||||
|
@ -145,19 +145,19 @@ bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData,
|
||||||
int16 boneIdx = 1;
|
int16 boneIdx = 1;
|
||||||
int16 tmpNumOfPoints = MIN<int16>(lastKeyFramePtr->boneframes.size() - 1, numOfBonesInAnim - 1);
|
int16 tmpNumOfPoints = MIN<int16>(lastKeyFramePtr->boneframes.size() - 1, numOfBonesInAnim - 1);
|
||||||
do {
|
do {
|
||||||
BoneFrame *boneState = Model::getBonesStateData(bodyPtr, boneIdx);
|
BoneFrame *boneState = bodyData.getBoneState(boneIdx);
|
||||||
const BoneFrame &boneFrame = keyFrame->boneframes[boneIdx];
|
const BoneFrame &boneFrame = keyFrame->boneframes[boneIdx];
|
||||||
const BoneFrame &lastBoneFrame = lastKeyFramePtr->boneframes[boneIdx];
|
const BoneFrame &lastBoneFrame = lastKeyFramePtr->boneframes[boneIdx];
|
||||||
|
|
||||||
boneState->type = boneFrame.type;
|
boneState->type = boneFrame.type;
|
||||||
switch (boneFrame.type) {
|
switch (boneFrame.type) {
|
||||||
case 0: // allow global rotate
|
case 0:
|
||||||
boneState->x = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.x, lastBoneFrame.x);
|
boneState->x = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.x, lastBoneFrame.x);
|
||||||
boneState->y = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.y, lastBoneFrame.y);
|
boneState->y = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.y, lastBoneFrame.y);
|
||||||
boneState->z = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.z, lastBoneFrame.z);
|
boneState->z = applyAnimStepRotation(deltaTime, keyFrameLength, boneFrame.z, lastBoneFrame.z);
|
||||||
break;
|
break;
|
||||||
case 1: // disallow global rotate
|
case 1:
|
||||||
case 2: // disallow global rotate + hide
|
case 2:
|
||||||
boneState->x = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.x, lastBoneFrame.x);
|
boneState->x = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.x, lastBoneFrame.x);
|
||||||
boneState->y = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.y, lastBoneFrame.y);
|
boneState->y = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.y, lastBoneFrame.y);
|
||||||
boneState->z = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.z, lastBoneFrame.z);
|
boneState->z = applyAnimStepTranslation(deltaTime, keyFrameLength, boneFrame.z, lastBoneFrame.z);
|
||||||
|
@ -172,8 +172,8 @@ bool Animations::setModelAnimation(int32 keyframeIdx, const AnimData &animData,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animations::setAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, uint8 *const bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
|
void Animations::setAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr) {
|
||||||
if (!Model::isAnimated(bodyPtr)) {
|
if (!bodyData.isAnimated()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,18 +194,18 @@ void Animations::setAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData,
|
||||||
animTimerDataPtr->ptr = animData.getKeyframe(keyframeIdx);
|
animTimerDataPtr->ptr = animData.getKeyframe(keyframeIdx);
|
||||||
animTimerDataPtr->time = _engine->lbaTime;
|
animTimerDataPtr->time = _engine->lbaTime;
|
||||||
|
|
||||||
const int16 numBones = Model::getNumBones(bodyPtr);
|
const int16 numBones = bodyData.getNumBones();
|
||||||
|
|
||||||
int16 numOfBonesInAnim = animData.getNumBoneframes();
|
int16 numOfBonesInAnim = animData.getNumBoneframes();
|
||||||
if (numOfBonesInAnim > numBones) {
|
if (numOfBonesInAnim > numBones) {
|
||||||
numOfBonesInAnim = numBones;
|
numOfBonesInAnim = numBones;
|
||||||
}
|
}
|
||||||
|
|
||||||
copyKeyFrameToState(keyFrame, bodyPtr, numOfBonesInAnim);
|
copyKeyFrameToState(keyFrame, bodyData, numOfBonesInAnim);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animations::stockAnimation(const uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr) {
|
void Animations::stockAnimation(const BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr) {
|
||||||
if (!Model::isAnimated(bodyPtr)) {
|
if (!bodyData.isAnimated()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,22 +215,22 @@ void Animations::stockAnimation(const uint8 *bodyPtr, AnimTimerDataStruct *animT
|
||||||
animTimerDataPtr->time = _engine->lbaTime;
|
animTimerDataPtr->time = _engine->lbaTime;
|
||||||
KeyFrame *keyframe = &animKeyframeBuf[animKeyframeBufIdx++];
|
KeyFrame *keyframe = &animKeyframeBuf[animKeyframeBufIdx++];
|
||||||
animTimerDataPtr->ptr = keyframe;
|
animTimerDataPtr->ptr = keyframe;
|
||||||
copyStateToKeyFrame(keyframe, bodyPtr);
|
copyStateToKeyFrame(keyframe, bodyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animations::copyStateToKeyFrame(KeyFrame *keyframe, const uint8 *bodyPtr) const {
|
void Animations::copyStateToKeyFrame(KeyFrame *keyframe, const BodyData &bodyData) const {
|
||||||
const int32 numBones = Model::getNumBones(bodyPtr);
|
const int32 numBones = bodyData.getNumBones();
|
||||||
keyframe->boneframes.clear();
|
keyframe->boneframes.clear();
|
||||||
keyframe->boneframes.reserve(numBones);
|
keyframe->boneframes.reserve(numBones);
|
||||||
for (int32 i = 0; i < numBones; ++i) {
|
for (int32 i = 0; i < numBones; ++i) {
|
||||||
const BoneFrame *boneState = Model::getBonesStateData(bodyPtr, i);
|
const BoneFrame *boneState = bodyData.getBoneState(i);
|
||||||
keyframe->boneframes.push_back(*boneState);
|
keyframe->boneframes.push_back(*boneState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animations::copyKeyFrameToState(const KeyFrame *keyframe, uint8 *bodyPtr, int32 numBones) const {
|
void Animations::copyKeyFrameToState(const KeyFrame *keyframe, BodyData &bodyData, int32 numBones) const {
|
||||||
for (int32 i = 0; i < numBones; ++i) {
|
for (int32 i = 0; i < numBones; ++i) {
|
||||||
BoneFrame *boneState = Model::getBonesStateData(bodyPtr, i);
|
BoneFrame *boneState = bodyData.getBoneState(i);
|
||||||
*boneState = keyframe->boneframes[i];
|
*boneState = keyframe->boneframes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,10 +436,10 @@ bool Animations::initAnim(AnimationTypes newAnim, AnimType animType, AnimationTy
|
||||||
|
|
||||||
if (actor->previousAnimIdx == -1) {
|
if (actor->previousAnimIdx == -1) {
|
||||||
// if no previous animation
|
// if no previous animation
|
||||||
setAnimAtKeyframe(0, _engine->_resources->animData[animIndex], _engine->_resources->bodyTable[actor->entity], &actor->animTimerData);
|
setAnimAtKeyframe(0, _engine->_resources->animData[animIndex], _engine->_resources->bodyData[actor->entity], &actor->animTimerData);
|
||||||
} else {
|
} else {
|
||||||
// interpolation between animations
|
// interpolation between animations
|
||||||
stockAnimation(_engine->_resources->bodyTable[actor->entity], &actor->animTimerData);
|
stockAnimation(_engine->_resources->bodyData[actor->entity], &actor->animTimerData);
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->previousAnimIdx = animIndex;
|
actor->previousAnimIdx = animIndex;
|
||||||
|
@ -568,7 +568,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
|
||||||
const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
|
const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
|
||||||
|
|
||||||
bool keyFramePassed = false;
|
bool keyFramePassed = false;
|
||||||
if (Model::isAnimated(_engine->_resources->bodyTable[actor->entity])) {
|
if (_engine->_resources->bodyData[actor->entity].isAnimated()) {
|
||||||
keyFramePassed = verifyAnimAtKeyframe(actor->animPosition, animData, &actor->animTimerData);
|
keyFramePassed = verifyAnimAtKeyframe(actor->animPosition, animData, &actor->animTimerData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ private:
|
||||||
*/
|
*/
|
||||||
bool verifyAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, AnimTimerDataStruct *animTimerDataPtr);
|
bool verifyAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, AnimTimerDataStruct *animTimerDataPtr);
|
||||||
|
|
||||||
void copyKeyFrameToState(const KeyFrame *keyframe, uint8 *bodyPtr, int32 numBones) const;
|
void copyKeyFrameToState(const KeyFrame *keyframe, BodyData &bodyData, int32 numBones) const;
|
||||||
void copyStateToKeyFrame(KeyFrame *keyframe, const uint8 *bodyPtr) const;
|
void copyStateToKeyFrame(KeyFrame *keyframe, const BodyData &bodyData) const;
|
||||||
|
|
||||||
int animKeyframeBufIdx = 0;
|
int animKeyframeBufIdx = 0;
|
||||||
KeyFrame animKeyframeBuf[32];
|
KeyFrame animKeyframeBuf[32];
|
||||||
|
@ -75,19 +75,19 @@ public:
|
||||||
* Set animation keyframe
|
* Set animation keyframe
|
||||||
* @param keyframIdx Animation keyframe index
|
* @param keyframIdx Animation keyframe index
|
||||||
* @param animData Animation data
|
* @param animData Animation data
|
||||||
* @param bodyPtr Body model poitner
|
* @param bodyData Body model data
|
||||||
* @param animTimerDataPtr Animation time data
|
* @param animTimerDataPtr Animation time data
|
||||||
*/
|
*/
|
||||||
void setAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, uint8 *const bodyPtr, AnimTimerDataStruct *animTimerDataPtr);
|
void setAnimAtKeyframe(int32 keyframeIdx, const AnimData &animData, BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set new body animation
|
* Set new body animation
|
||||||
* @param keyframeIdx Animation key frame index
|
* @param keyframeIdx Animation key frame index
|
||||||
* @param animData Animation data
|
* @param animData Animation data
|
||||||
* @param bodyPtr Body model poitner
|
* @param bodyData Body model data
|
||||||
* @param animTimerDataPtr Animation time data
|
* @param animTimerDataPtr Animation time data
|
||||||
*/
|
*/
|
||||||
bool setModelAnimation(int32 keyframeIdx, const AnimData &animData, uint8 *const bodyPtr, AnimTimerDataStruct *animTimerDataPtr);
|
bool setModelAnimation(int32 keyframeIdx, const AnimData &animData, BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get entity anim index (This is taken from File3D entities)
|
* Get entity anim index (This is taken from File3D entities)
|
||||||
|
@ -98,10 +98,10 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stock animation - copy the next keyFrame from a different buffer
|
* Stock animation - copy the next keyFrame from a different buffer
|
||||||
* @param bodyPtr Body model poitner
|
* @param bodyData Body model data
|
||||||
* @param animTimerDataPtr Animation time data
|
* @param animTimerDataPtr Animation time data
|
||||||
*/
|
*/
|
||||||
void stockAnimation(const uint8 *bodyPtr, AnimTimerDataStruct *animTimerDataPtr);
|
void stockAnimation(const BodyData &bodyData, AnimTimerDataStruct *animTimerDataPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize animation
|
* Initialize animation
|
||||||
|
|
|
@ -321,11 +321,11 @@ void GameState::processFoundItem(int32 item) {
|
||||||
const int32 itemCameraY = _engine->_grid->newCamera.y * BRICK_HEIGHT;
|
const int32 itemCameraY = _engine->_grid->newCamera.y * BRICK_HEIGHT;
|
||||||
const int32 itemCameraZ = _engine->_grid->newCamera.z * BRICK_SIZE;
|
const int32 itemCameraZ = _engine->_grid->newCamera.z * BRICK_SIZE;
|
||||||
|
|
||||||
uint8 *bodyPtr = _engine->_resources->bodyTable[_engine->_scene->sceneHero->entity];
|
BodyData &bodyData = _engine->_resources->bodyData[_engine->_scene->sceneHero->entity];
|
||||||
const int32 bodyX = _engine->_scene->sceneHero->pos.x - itemCameraX;
|
const int32 bodyX = _engine->_scene->sceneHero->pos.x - itemCameraX;
|
||||||
const int32 bodyY = _engine->_scene->sceneHero->pos.y - itemCameraY;
|
const int32 bodyY = _engine->_scene->sceneHero->pos.y - itemCameraY;
|
||||||
const int32 bodyZ = _engine->_scene->sceneHero->pos.z - itemCameraZ;
|
const int32 bodyZ = _engine->_scene->sceneHero->pos.z - itemCameraZ;
|
||||||
_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyPtr);
|
_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyData);
|
||||||
_engine->_interface->setClip(_engine->_redraw->renderRect);
|
_engine->_interface->setClip(_engine->_redraw->renderRect);
|
||||||
|
|
||||||
const int32 itemX = (_engine->_scene->sceneHero->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
|
const int32 itemX = (_engine->_scene->sceneHero->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
|
||||||
|
@ -365,7 +365,7 @@ void GameState::processFoundItem(int32 item) {
|
||||||
|
|
||||||
AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
|
AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
|
||||||
|
|
||||||
_engine->_animations->stockAnimation(bodyPtr, &_engine->_scene->sceneHero->animTimerData);
|
_engine->_animations->stockAnimation(bodyData, &_engine->_scene->sceneHero->animTimerData);
|
||||||
|
|
||||||
uint currentAnimState = 0;
|
uint currentAnimState = 0;
|
||||||
|
|
||||||
|
@ -391,14 +391,14 @@ void GameState::processFoundItem(int32 item) {
|
||||||
_engine->_interface->resetClip();
|
_engine->_interface->resetClip();
|
||||||
initEngineProjections();
|
initEngineProjections();
|
||||||
|
|
||||||
if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, bodyPtr, &_engine->_scene->sceneHero->animTimerData)) {
|
if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, bodyData, &_engine->_scene->sceneHero->animTimerData)) {
|
||||||
currentAnimState++; // keyframe
|
currentAnimState++; // keyframe
|
||||||
if (currentAnimState >= currentAnimData.getNumKeyframes()) {
|
if (currentAnimState >= currentAnimData.getNumKeyframes()) {
|
||||||
currentAnimState = currentAnimData.getLoopFrame();
|
currentAnimState = currentAnimData.getLoopFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyPtr);
|
_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyData);
|
||||||
_engine->_interface->setClip(_engine->_redraw->renderRect);
|
_engine->_interface->setClip(_engine->_redraw->renderRect);
|
||||||
_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
|
_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
|
||||||
_engine->_redraw->addRedrawArea(_engine->_redraw->renderRect);
|
_engine->_redraw->addRedrawArea(_engine->_redraw->renderRect);
|
||||||
|
@ -495,8 +495,8 @@ void GameState::processGameoverAnimation() {
|
||||||
_engine->setPalette(_engine->_screens->paletteRGBA);
|
_engine->setPalette(_engine->_screens->paletteRGBA);
|
||||||
_engine->flip();
|
_engine->flip();
|
||||||
_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
|
_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
|
||||||
uint8 *gameOverPtr = nullptr;
|
BodyData gameOverPtr;
|
||||||
if (HQR::getAllocEntry(&gameOverPtr, Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL) == 0) {
|
if (!gameOverPtr.loadFromHQR(Resources::HQR_RESS_FILE, RESSHQR_GAMEOVERMDL)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +512,6 @@ void GameState::processGameoverAnimation() {
|
||||||
ScopedFPS scopedFps(66);
|
ScopedFPS scopedFps(66);
|
||||||
_engine->readKeys();
|
_engine->readKeys();
|
||||||
if (_engine->shouldQuit()) {
|
if (_engine->shouldQuit()) {
|
||||||
free(gameOverPtr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,7 +535,6 @@ void GameState::processGameoverAnimation() {
|
||||||
_engine->delaySkip(2000);
|
_engine->delaySkip(2000);
|
||||||
|
|
||||||
_engine->_interface->resetClip();
|
_engine->_interface->resetClip();
|
||||||
free(gameOverPtr);
|
|
||||||
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
_engine->_screens->copyScreen(_engine->workVideoBuffer, _engine->frontVideoBuffer);
|
||||||
_engine->flip();
|
_engine->flip();
|
||||||
initEngineProjections();
|
initEngineProjections();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue