2020-10-14 15:16:30 +02:00
|
|
|
/* 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 2
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
*/
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
#ifndef TWINE_RENDERER_H
|
|
|
|
#define TWINE_RENDERER_H
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-12-07 17:07:01 +01:00
|
|
|
#include "common/endian.h"
|
2020-11-24 18:17:12 +01:00
|
|
|
#include "common/rect.h"
|
2020-12-13 23:08:23 +01:00
|
|
|
#include "common/scummsys.h"
|
2020-12-13 22:04:48 +01:00
|
|
|
#include "twine/parser/body.h"
|
2020-12-23 14:46:30 +01:00
|
|
|
#include "twine/twine.h"
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-08 13:42:48 +01:00
|
|
|
#define POLYGONTYPE_FLAT 0
|
|
|
|
#define POLYGONTYPE_COPPER 1
|
|
|
|
#define POLYGONTYPE_BOPPER 2
|
|
|
|
#define POLYGONTYPE_MARBLE 3
|
|
|
|
#define POLYGONTYPE_TELE 4
|
|
|
|
#define POLYGONTYPE_TRAS 5
|
|
|
|
#define POLYGONTYPE_TRAME 6
|
|
|
|
#define POLYGONTYPE_GOURAUD 7
|
|
|
|
#define POLYGONTYPE_DITHER 8
|
|
|
|
|
2020-11-29 17:55:44 +01:00
|
|
|
namespace Common {
|
|
|
|
class MemoryReadStream;
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
namespace TwinE {
|
2020-11-14 10:43:01 +01:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
class TwinEEngine;
|
2020-11-14 10:43:01 +01:00
|
|
|
|
2020-11-29 14:26:56 +01:00
|
|
|
struct Vertex {
|
2020-11-27 23:08:12 +01:00
|
|
|
int16 colorIndex = 0;
|
2020-11-29 14:26:56 +01:00
|
|
|
int16 x = 0;
|
|
|
|
int16 y = 0;
|
|
|
|
};
|
|
|
|
|
2020-11-29 18:06:29 +01:00
|
|
|
struct CmdRenderPolygon {
|
2020-11-29 14:26:56 +01:00
|
|
|
uint8 renderType = 0;
|
|
|
|
uint8 numVertices = 0;
|
|
|
|
int16 colorIndex = 0;
|
|
|
|
// followed by Vertex array
|
2020-11-27 23:08:12 +01:00
|
|
|
};
|
|
|
|
|
2020-11-29 22:04:29 +01:00
|
|
|
struct Matrix {
|
2020-12-13 23:08:23 +01:00
|
|
|
int32 row1[3]{0, 0, 0};
|
|
|
|
int32 row2[3]{0, 0, 0};
|
|
|
|
int32 row3[3]{0, 0, 0};
|
2020-11-29 22:04:29 +01:00
|
|
|
};
|
|
|
|
|
2020-12-14 11:02:13 +01:00
|
|
|
inline Matrix operator*(const Matrix &matrix, const Vec3 &vec) {
|
|
|
|
Matrix out;
|
|
|
|
out.row1[0] = matrix.row1[0] * vec.x;
|
|
|
|
out.row1[1] = matrix.row1[1] * vec.x;
|
|
|
|
out.row1[2] = matrix.row1[2] * vec.x;
|
|
|
|
|
|
|
|
out.row2[0] = matrix.row2[0] * vec.y;
|
|
|
|
out.row2[1] = matrix.row2[1] * vec.y;
|
|
|
|
out.row2[2] = matrix.row2[2] * vec.y;
|
|
|
|
|
|
|
|
out.row3[0] = matrix.row3[0] * vec.z;
|
|
|
|
out.row3[1] = matrix.row3[1] * vec.z;
|
|
|
|
out.row3[2] = matrix.row3[2] * vec.z;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2020-11-29 22:47:17 +01:00
|
|
|
struct Model {
|
|
|
|
struct BodyFlags {
|
2020-12-07 17:07:01 +01:00
|
|
|
uint16 unk1 : 1; // 1 << 0
|
|
|
|
uint16 animated : 1; // 1 << 1
|
|
|
|
uint16 unk3 : 1; // 1 << 2
|
|
|
|
uint16 unk4 : 1; // 1 << 3
|
|
|
|
uint16 unk5 : 1; // 1 << 4
|
|
|
|
uint16 unk6 : 1; // 1 << 5
|
|
|
|
uint16 unk7 : 1; // 1 << 6
|
|
|
|
uint16 alreadyPrepared : 1; // 1 << 7
|
|
|
|
uint16 unk9 : 1; // 1 << 8
|
|
|
|
uint16 unk10 : 1; // 1 << 9
|
|
|
|
uint16 unk11 : 1; // 1 << 10
|
|
|
|
uint16 unk12 : 1; // 1 << 11
|
|
|
|
uint16 unk13 : 1; // 1 << 12
|
|
|
|
uint16 unk14 : 1; // 1 << 13
|
|
|
|
uint16 unk15 : 1; // 1 << 14
|
|
|
|
uint16 unk16 : 1; // 1 << 15
|
2020-11-29 22:47:17 +01:00
|
|
|
} bodyFlag;
|
|
|
|
int16 minsx = 0;
|
|
|
|
int16 maxsx = 0;
|
|
|
|
int16 minsy = 0;
|
|
|
|
int16 maxsy = 0;
|
|
|
|
int16 minsz = 0;
|
|
|
|
int16 maxsz = 0;
|
|
|
|
int16 offsetToData = 0;
|
2020-12-07 17:07:01 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static inline bool isAnimated(const uint8 *bodyPtr) {
|
2020-12-07 17:07:01 +01:00
|
|
|
const int16 bodyHeader = READ_LE_INT16(bodyPtr);
|
|
|
|
return (bodyHeader & 2) != 0;
|
|
|
|
}
|
2020-12-13 11:44:59 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static inline bool isAnimated(const BodyData &bodyPtr) {
|
2020-12-13 22:04:48 +01:00
|
|
|
return bodyPtr.isAnimated();
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static uint8 *getData(uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
return bodyPtr + 0x1A;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getData(const uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
return bodyPtr + 0x1A;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getVerticesBaseData(const uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
return getData(bodyPtr) + 2;
|
2020-12-13 11:44:59 +01:00
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const Common::Array<BodyVertex> &getVerticesBaseData(const BodyData &bodyPtr) {
|
2020-12-13 22:47:46 +01:00
|
|
|
return bodyPtr.getVertices();
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static uint8 *getBonesData(uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
uint8 *verticesBase = getData(bodyPtr);
|
|
|
|
const int16 numVertices = READ_LE_INT16(verticesBase);
|
|
|
|
return verticesBase + 2 + numVertices * 6;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getBonesData(const uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
const uint8 *verticesBase = getData(bodyPtr);
|
2020-12-13 11:44:59 +01:00
|
|
|
const int16 numVertices = READ_LE_INT16(verticesBase);
|
2020-12-13 15:49:11 +01:00
|
|
|
return verticesBase + 2 + numVertices * 6;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getBonesStateData(const uint8 *bodyPtr, int boneIdx) {
|
2020-12-13 17:49:37 +01:00
|
|
|
return getBonesBaseData(bodyPtr) + 8 + (boneIdx * 38);
|
2020-12-13 15:49:11 +01:00
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static uint8 *getBonesStateData(uint8 *bodyPtr, int boneIdx) {
|
2020-12-13 17:49:37 +01:00
|
|
|
return getBonesBaseData(bodyPtr) + 8 + (boneIdx * 38);
|
2020-12-13 15:49:11 +01:00
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static BoneFrame *getBonesStateData(BodyData &bodyPtr, int boneIdx) {
|
2020-12-13 22:04:48 +01:00
|
|
|
return bodyPtr.getBoneState(boneIdx);
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const BoneFrame *getBonesStateData(const BodyData &bodyPtr, int boneIdx) {
|
2020-12-13 22:04:48 +01:00
|
|
|
return bodyPtr.getBoneState(boneIdx);
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static uint8 *getBonesBaseData(uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
return getBonesData(bodyPtr) + 2;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getBonesBaseData(const uint8 *bodyPtr, int boneIdx = 0) {
|
2020-12-13 22:25:50 +01:00
|
|
|
return getBonesData(bodyPtr) + 2 + (boneIdx * 38);
|
2020-12-13 11:44:59 +01:00
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const BoneFrame *getBonesBaseData(const BodyData &bodyPtr, int boneIdx = 0) {
|
2020-12-13 22:47:46 +01:00
|
|
|
return bodyPtr.getBoneState(boneIdx);
|
|
|
|
}
|
|
|
|
|
2020-12-13 11:44:59 +01:00
|
|
|
static int16 getNumBones(const uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
const uint8 *verticesBase = getData(bodyPtr);
|
2020-12-13 11:44:59 +01:00
|
|
|
const int16 numVertices = READ_LE_INT16(verticesBase);
|
|
|
|
const uint8 *bonesBase = verticesBase + 2 + numVertices * 6;
|
|
|
|
return READ_LE_INT16(bonesBase);
|
|
|
|
}
|
2020-12-13 15:49:11 +01:00
|
|
|
|
2020-12-13 22:04:48 +01:00
|
|
|
static int16 getNumBones(const BodyData &bodyPtr) {
|
|
|
|
return bodyPtr.getNumBones();
|
|
|
|
}
|
|
|
|
|
2020-12-13 15:49:11 +01:00
|
|
|
static int16 getNumVertices(const uint8 *bodyPtr) {
|
|
|
|
const uint8 *verticesBase = getData(bodyPtr);
|
|
|
|
return READ_LE_INT16(verticesBase);
|
|
|
|
}
|
|
|
|
|
2020-12-13 22:04:48 +01:00
|
|
|
static int16 getNumVertices(const BodyData &bodyPtr) {
|
|
|
|
return bodyPtr.getNumVertices();
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static uint8 *getShadesData(uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
uint8 *bonesBase = getBonesBaseData(bodyPtr);
|
|
|
|
const int16 numBones = getNumBones(bodyPtr);
|
|
|
|
return bonesBase + numBones * 38;
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getShadesBaseData(const uint8 *bodyPtr, int16 shadeIdx = 0) {
|
2020-12-13 22:21:38 +01:00
|
|
|
return getShadesData(bodyPtr) + 2 + (shadeIdx * 8);
|
2020-12-13 15:49:11 +01:00
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const BodyShade *getShadesBaseData(const BodyData &bodyPtr, int16 shadeIdx = 0) {
|
2020-12-13 22:25:50 +01:00
|
|
|
return bodyPtr.getShade(shadeIdx);
|
|
|
|
}
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getShadesData(const uint8 *bodyPtr) {
|
2020-12-13 15:49:11 +01:00
|
|
|
const uint8 *bonesBase = getBonesBaseData(bodyPtr);
|
|
|
|
const int16 numBones = getNumBones(bodyPtr);
|
|
|
|
return bonesBase + numBones * 38;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int16 getNumShades(const uint8 *bodyPtr) {
|
|
|
|
const uint8 *shadesBase = getShadesData(bodyPtr);
|
|
|
|
return READ_LE_INT16(shadesBase);
|
|
|
|
}
|
|
|
|
|
2020-12-13 22:04:48 +01:00
|
|
|
static int16 getNumShades(const BodyData &bodyPtr) {
|
|
|
|
return bodyPtr.getShades().size();
|
|
|
|
}
|
|
|
|
|
2020-12-13 15:49:11 +01:00
|
|
|
static int16 getNumShadesBone(const uint8 *bodyPtr, int boneIdx) {
|
|
|
|
const uint8 *bonesBase = getBonesBaseData(bodyPtr);
|
|
|
|
return READ_LE_INT16(bonesBase + (boneIdx * 38) + 18);
|
|
|
|
}
|
2020-12-13 22:04:48 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static int16 getNumShadesBone(const BodyData &bodyPtr, int boneIdx) {
|
2020-12-13 22:04:48 +01:00
|
|
|
return bodyPtr.getBone(boneIdx)->numOfShades;
|
|
|
|
}
|
2020-12-13 22:21:38 +01:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
static const uint8 *getPolygonData(const uint8 *bodyPtr) {
|
|
|
|
const uint8 *shades = getShadesBaseData(bodyPtr);
|
2020-12-13 22:21:38 +01:00
|
|
|
const int16 numShades = getNumShades(bodyPtr);
|
|
|
|
if (numShades <= 0) {
|
|
|
|
return shades;
|
|
|
|
}
|
|
|
|
const int16 bones = getNumBones(bodyPtr);
|
|
|
|
for (int16 boneIdx = 0; boneIdx < bones; ++boneIdx) {
|
|
|
|
int16 numOfShades = Model::getNumShadesBone(bodyPtr, boneIdx);
|
|
|
|
shades += numOfShades * 8;
|
|
|
|
}
|
|
|
|
return shades;
|
|
|
|
}
|
2020-11-29 22:47:17 +01:00
|
|
|
};
|
|
|
|
|
2020-12-11 19:34:22 +01:00
|
|
|
#include "common/pack-start.h"
|
|
|
|
struct elementEntry {
|
|
|
|
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;
|
|
|
|
int32 numOfShades = 0; // field_10
|
|
|
|
int32 field_14 = 0;
|
|
|
|
int32 field_18 = 0;
|
|
|
|
int32 y = 0;
|
|
|
|
int32 field_20 = 0;
|
|
|
|
int16 field_24 = 0;
|
|
|
|
};
|
|
|
|
#include "common/pack-end.h"
|
|
|
|
static_assert(sizeof(elementEntry) == 38, "Unexpected elementEntry size");
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
class Renderer {
|
|
|
|
private:
|
|
|
|
TwinEEngine *_engine;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-29 17:55:44 +01:00
|
|
|
struct RenderCommand {
|
2020-10-14 15:16:30 +02:00
|
|
|
int16 depth = 0;
|
|
|
|
int16 renderType = 0;
|
|
|
|
uint8 *dataPtr = nullptr;
|
2020-10-21 11:23:09 +02:00
|
|
|
};
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-29 18:03:12 +01:00
|
|
|
struct CmdRenderLine {
|
|
|
|
uint8 colorIndex = 0;
|
|
|
|
uint8 unk1 = 0;
|
|
|
|
uint8 unk2 = 0;
|
|
|
|
uint8 unk3 = 0;
|
|
|
|
int16 x1 = 0;
|
|
|
|
int16 y1 = 0;
|
|
|
|
int16 x2 = 0;
|
|
|
|
int16 y2 = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CmdRenderSphere {
|
|
|
|
int8 colorIndex = 0;
|
|
|
|
int16 x = 0;
|
|
|
|
int16 y = 0;
|
|
|
|
int16 radius = 0;
|
|
|
|
};
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
#include "common/pack-start.h"
|
2020-10-21 11:23:09 +02:00
|
|
|
struct pointTab {
|
2020-11-06 00:11:54 +01:00
|
|
|
int16 x = 0;
|
|
|
|
int16 y = 0;
|
|
|
|
int16 z = 0;
|
2020-10-21 11:23:09 +02:00
|
|
|
};
|
2020-12-13 23:08:23 +01:00
|
|
|
#include "common/pack-end.h"
|
2020-11-08 20:30:49 +01:00
|
|
|
static_assert(sizeof(pointTab) == 6, "Unexpected pointTab size");
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-21 11:23:09 +02:00
|
|
|
struct polyVertexHeader {
|
2020-10-14 15:16:30 +02:00
|
|
|
int16 shadeEntry = 0;
|
|
|
|
int16 dataOffset = 0;
|
2020-10-21 11:23:09 +02:00
|
|
|
};
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-11-29 20:21:52 +01:00
|
|
|
struct ModelData {
|
|
|
|
pointTab computedPoints[800];
|
|
|
|
pointTab flattenPoints[800];
|
2020-12-13 23:08:23 +01:00
|
|
|
int16 shadeTable[500]{0};
|
2020-11-29 20:21:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
ModelData _modelData;
|
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
bool renderAnimatedModel(ModelData *modelData, const uint8 *bodyPtr, RenderCommand *renderCmds);
|
2020-11-27 23:37:13 +01:00
|
|
|
void circleFill(int32 x, int32 y, int32 radius, uint8 color);
|
2020-12-13 23:08:23 +01:00
|
|
|
bool renderModelElements(int32 numOfPrimitives, const uint8 *polygonPtr, RenderCommand **renderCmds, ModelData *modelData);
|
2020-10-30 20:29:10 +01:00
|
|
|
void getCameraAnglePositions(int32 x, int32 y, int32 z);
|
2020-11-29 22:04:29 +01:00
|
|
|
void applyRotation(Matrix *targetMatrix, const Matrix *currentMatrix);
|
|
|
|
void applyPointsRotation(const pointTab *pointsPtr, int32 numPoints, pointTab *destPoints, const Matrix *rotationMatrix);
|
2020-11-29 22:13:30 +01:00
|
|
|
void processRotatedElement(Matrix *targetMatrix, const pointTab *pointsPtr, int32 rotZ, int32 rotY, int32 rotX, const elementEntry *elemPtr, ModelData *modelData);
|
2020-11-29 22:04:29 +01:00
|
|
|
void applyPointsTranslation(const pointTab *pointsPtr, int32 numPoints, pointTab *destPoints, const Matrix *translationMatrix);
|
2020-11-29 22:13:30 +01:00
|
|
|
void processTranslatedElement(Matrix *targetMatrix, const pointTab *pointsPtr, int32 rotX, int32 rotY, int32 rotZ, const elementEntry *elemPtr, ModelData *modelData);
|
2021-01-26 00:39:26 +01:00
|
|
|
void translateGroup(int32 x, int32 y, int32 z);
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
// ---- variables ----
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-02-26 10:27:18 +01:00
|
|
|
Vec3 baseTransPos;
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2021-01-26 01:04:39 +01:00
|
|
|
int32 cameraDepthOffset = 0; // cameraVar1
|
|
|
|
int32 cameraScaleY = 0; // cameraVar2
|
|
|
|
int32 cameraScaleZ = 0; // cameraVar3
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
// ---
|
2020-10-14 14:20:38 +02:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
int32 renderAngleX = 0; // _angleX
|
|
|
|
int32 renderAngleY = 0; // _angleY
|
|
|
|
int32 renderAngleZ = 0; // _angleZ
|
|
|
|
|
2021-02-26 10:27:18 +01:00
|
|
|
Vec3 renderPos;
|
2020-10-14 15:16:30 +02:00
|
|
|
|
|
|
|
// ---
|
|
|
|
|
2020-11-29 22:04:29 +01:00
|
|
|
Matrix baseMatrix;
|
|
|
|
Matrix matricesTable[30 + 1];
|
|
|
|
Matrix shadeMatrix;
|
2020-12-14 11:02:13 +01:00
|
|
|
Vec3 lightPos;
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2020-11-29 17:55:44 +01:00
|
|
|
RenderCommand _renderCmds[1000];
|
2020-12-13 23:08:23 +01:00
|
|
|
uint8 renderCoordinatesBuffer[10000]{0};
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2021-01-07 22:21:07 +01:00
|
|
|
int32 _polyTabSize = 0;
|
|
|
|
int16 *_polyTab = nullptr;
|
|
|
|
int16 *_polyTab2 = nullptr;
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2021-01-08 12:27:11 +01:00
|
|
|
bool isUsingOrthoProjection = false;
|
2020-10-27 17:30:15 +01:00
|
|
|
|
2020-11-26 23:33:57 +01:00
|
|
|
void renderPolygonsCopper(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsBopper(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsFlat(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsTele(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsTras(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonTrame(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsGouraud(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsDither(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
void renderPolygonsMarble(uint8 *out, int vtop, int32 vsize, int32 color) const;
|
|
|
|
|
2020-12-23 11:51:24 +01:00
|
|
|
void computeBoundingBox(Vertex *vertices, int32 numVertices, int &vleft, int &vright, int &vtop, int &vbottom) const;
|
2021-02-13 14:19:05 +01:00
|
|
|
void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
|
2020-11-08 13:22:37 +01:00
|
|
|
|
2020-11-29 17:55:44 +01:00
|
|
|
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
|
2020-12-13 23:08:23 +01:00
|
|
|
uint8 *preparePolygons(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
|
|
|
uint8 *prepareSpheres(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
|
|
|
uint8 *prepareLines(Common::MemoryReadStream &stream, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
|
2020-11-29 17:55:44 +01:00
|
|
|
|
2021-01-30 19:23:39 +01:00
|
|
|
void baseMatrixTranspose();
|
|
|
|
|
2021-02-17 21:30:14 +01:00
|
|
|
void renderHolomapPolygons(int32 top, int32 bottom);
|
2021-02-13 15:40:14 +01:00
|
|
|
void computeHolomapPolygon(int32 y1, int32 x1, int32 y2, int32 x2, int16 *polygonTabPtr);
|
2021-02-17 21:30:14 +01:00
|
|
|
void fillHolomapPolygons(const Vertex &vertex1, const Vertex &vertex2, const Vertex &vertex3, const Vertex &vertex4, int32 &top, int32 &bottom);
|
2021-02-13 15:26:19 +01:00
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
public:
|
2020-12-13 12:50:59 +01:00
|
|
|
Renderer(TwinEEngine *engine);
|
2021-01-07 22:21:07 +01:00
|
|
|
~Renderer();
|
|
|
|
|
|
|
|
void init(int32 w, int32 h);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2021-02-26 10:10:30 +01:00
|
|
|
Vec3 projPosScreen;
|
2021-02-26 10:18:07 +01:00
|
|
|
Vec3 projPos;
|
2021-02-26 10:12:16 +01:00
|
|
|
Vec3 baseRotPos;
|
2021-02-26 10:16:38 +01:00
|
|
|
Vec3 orthoProjPos;
|
2021-02-26 10:23:21 +01:00
|
|
|
Vec3 destPos;
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
const int16 *const shadeAngleTab3;
|
2020-10-14 15:16:30 +02:00
|
|
|
|
|
|
|
void setLightVector(int32 angleX, int32 angleY, int32 angleZ);
|
2021-01-12 22:44:58 +01:00
|
|
|
void getBaseRotationPosition(int32 x, int32 y, int32 z);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2020-12-09 22:52:17 +01:00
|
|
|
static void prepareIsoModel(uint8 *bodyPtr);
|
2020-11-29 18:06:29 +01:00
|
|
|
void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2021-02-25 17:52:13 +01:00
|
|
|
inline int32 projectPositionOnScreen(const Vec3& pos) {
|
|
|
|
return projectPositionOnScreen(pos.x, pos.y, pos.z);
|
|
|
|
}
|
|
|
|
|
2020-10-14 15:16:30 +02:00
|
|
|
int32 projectPositionOnScreen(int32 cX, int32 cY, int32 cZ);
|
2021-01-26 01:04:39 +01:00
|
|
|
void setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleY, int32 scaleZ);
|
2020-10-14 15:16:30 +02:00
|
|
|
void setCameraAngle(int32 transPosX, int32 transPosY, int32 transPosZ, int32 rotPosX, int32 rotPosY, int32 rotPosZ, int32 param6);
|
2020-10-30 20:29:10 +01:00
|
|
|
void setBaseTranslation(int32 x, int32 y, int32 z);
|
2021-01-30 19:23:39 +01:00
|
|
|
void setBaseRotation(int32 x, int32 y, int32 z, bool transpose = false);
|
2020-10-30 20:29:10 +01:00
|
|
|
void setOrthoProjection(int32 x, int32 y, int32 z);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2020-12-13 23:08:23 +01:00
|
|
|
bool renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const uint8 *bodyPtr);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2021-02-25 05:53:09 +01:00
|
|
|
/**
|
|
|
|
* @param angle A value of @c -1 means that the model is automatically rotated
|
|
|
|
*/
|
2020-12-13 17:43:01 +01:00
|
|
|
void renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const uint8 *bodyPtr);
|
2021-02-25 05:53:09 +01:00
|
|
|
/**
|
|
|
|
* @param angle A value of @c -1 means that the model is automatically rotated
|
|
|
|
*/
|
2020-12-13 17:43:01 +01:00
|
|
|
void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const uint8 *bodyPtr);
|
2020-10-14 15:16:30 +02:00
|
|
|
|
2020-12-13 17:43:01 +01:00
|
|
|
void renderInventoryItem(int32 x, int32 y, const uint8 *bodyPtr, int32 angle, int32 param);
|
2021-02-13 14:50:15 +01:00
|
|
|
|
2021-02-17 18:14:32 +01:00
|
|
|
void renderHolomapVertices(const Vertex vertexCoordinates[3], const Vertex vertexCoordinates2[3]);
|
2020-10-14 15:16:30 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace TwinE
|
2020-10-14 14:20:38 +02:00
|
|
|
|
|
|
|
#endif
|