scummvm/engines/twine/renderer.h

365 lines
11 KiB
C
Raw Normal View History

/* 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
#ifndef TWINE_RENDERER_H
#define TWINE_RENDERER_H
2020-10-14 14:20:38 +02:00
#include "common/endian.h"
#include "common/scummsys.h"
#include "common/rect.h"
2020-10-14 14:20:38 +02: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
namespace Common {
class MemoryReadStream;
}
namespace TwinE {
2020-11-14 10:43:01 +01:00
class TwinEEngine;
2020-11-14 10:43:01 +01:00
2020-11-29 14:26:56 +01:00
struct Vertex {
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-29 22:04:29 +01:00
struct Matrix {
int32 row1[3] {0, 0, 0};
int32 row2[3] {0, 0, 0};
int32 row3[3] {0, 0, 0};
};
struct Model {
struct BodyFlags {
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
} bodyFlag;
int16 minsx = 0;
int16 maxsx = 0;
int16 minsy = 0;
int16 maxsy = 0;
int16 minsz = 0;
int16 maxsz = 0;
int16 offsetToData = 0;
static inline bool isAnimated(const uint8* bodyPtr) {
const int16 bodyHeader = READ_LE_INT16(bodyPtr);
return (bodyHeader & 2) != 0;
}
2020-12-13 15:49:11 +01:00
static uint8* getData(uint8 *bodyPtr) {
return bodyPtr + 0x1A;
}
static const uint8* getData(const uint8 *bodyPtr) {
return bodyPtr + 0x1A;
}
static const uint8* getVerticesBaseData(const uint8 *bodyPtr) {
return getData(bodyPtr) + 2;
}
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;
}
static const uint8* getBonesData(const uint8 *bodyPtr) {
const uint8 *verticesBase = getData(bodyPtr);
const int16 numVertices = READ_LE_INT16(verticesBase);
2020-12-13 15:49:11 +01:00
return verticesBase + 2 + numVertices * 6;
}
static const uint8* getBonesStateData(const uint8 *bodyPtr, int boneIdx) {
return getBonesBaseData(bodyPtr) + 8 + (boneIdx * 38);
2020-12-13 15:49:11 +01:00
}
static uint8* getBonesStateData(uint8 *bodyPtr, int boneIdx) {
return getBonesBaseData(bodyPtr) + 8 + (boneIdx * 38);
2020-12-13 15:49:11 +01:00
}
static uint8* getBonesBaseData(uint8 *bodyPtr) {
return getBonesData(bodyPtr) + 2;
}
static const uint8* getBonesBaseData(const uint8 *bodyPtr) {
return getBonesData(bodyPtr) + 2;
}
static int16 getNumBones(const uint8 *bodyPtr) {
2020-12-13 15:49:11 +01:00
const uint8 *verticesBase = getData(bodyPtr);
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
static int16 getNumVertices(const uint8 *bodyPtr) {
const uint8 *verticesBase = getData(bodyPtr);
return READ_LE_INT16(verticesBase);
}
static uint8* getShadesData(uint8 *bodyPtr) {
uint8 *bonesBase = getBonesBaseData(bodyPtr);
const int16 numBones = getNumBones(bodyPtr);
return bonesBase + numBones * 38;
}
2020-12-13 17:43:01 +01:00
static const uint8* getShadesBaseData(const uint8 *bodyPtr) {
2020-12-13 15:49:11 +01:00
return getShadesData(bodyPtr) + 2;
}
static const uint8* getShadesData(const uint8 *bodyPtr) {
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);
}
static int16 getNumShadesBone(const uint8 *bodyPtr, int boneIdx) {
const uint8 *bonesBase = getBonesBaseData(bodyPtr);
return READ_LE_INT16(bonesBase + (boneIdx * 38) + 18);
}
};
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");
class Renderer {
private:
TwinEEngine *_engine;
2020-10-14 14:20:38 +02:00
struct RenderCommand {
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-11-08 20:30:49 +01:00
#include "common/pack-start.h"
2020-10-21 11:23:09 +02:00
struct pointTab {
int16 x = 0;
int16 y = 0;
int16 z = 0;
2020-10-21 11:23:09 +02:00
};
2020-11-08 20:30:49 +01:00
#include "common/pack-end.h"
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 {
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];
int16 shadeTable[500] {0};
};
ModelData _modelData;
2020-12-13 17:43:01 +01:00
int32 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 17:34:07 +01:00
int32 renderModelElements(int32 numOfPrimitives, const uint8 *polygonPtr, RenderCommand** renderCmds, ModelData *modelData);
2020-10-30 20:29:10 +01:00
void getBaseRotationPosition(int32 x, int32 y, int32 z);
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);
void translateGroup(int16 ax, int16 bx, int16 cx);
2020-10-14 14:20:38 +02:00
// ---- variables ----
2020-10-14 14:20:38 +02:00
int32 baseTransPosX = 0; // setSomething2Var1
int32 baseTransPosY = 0; // setSomething2Var2
int32 baseTransPosZ = 0; // setSomething2Var3
2020-10-14 14:20:38 +02:00
int32 baseRotPosX = 0; // setSomething3Var12
int32 baseRotPosY = 0; // setSomething3Var14
int32 baseRotPosZ = 0; // setSomething3Var16
2020-10-14 14:20:38 +02:00
int32 cameraPosX = 0; // cameraVar1
int32 cameraPosY = 0; // cameraVar2
int32 cameraPosZ = 0; // cameraVar3
2020-10-14 14:20:38 +02:00
// ---
2020-10-14 14:20:38 +02:00
int32 renderAngleX = 0; // _angleX
int32 renderAngleY = 0; // _angleY
int32 renderAngleZ = 0; // _angleZ
int32 renderX = 0; // _X
int32 renderY = 0; // _Y
int32 renderZ = 0; // _Z
// ---
2020-11-29 22:04:29 +01:00
Matrix baseMatrix;
Matrix matricesTable[30 + 1];
Matrix shadeMatrix;
int32 lightX = 0;
int32 lightY = 0;
int32 lightZ = 0;
RenderCommand _renderCmds[1000];
RenderCommand _renderCmdsSortedByDepth[1000];
uint8 renderCoordinatesBuffer[10000] {0};
int16 polyTab[960] {0};
int16 polyTab2[960] {0};
// end render polygon vars
2020-11-06 00:31:03 +01:00
bool isUsingOrhoProjection = false;
2020-10-27 17:30:15 +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-11-29 14:26:56 +01:00
void computePolygons(int16 polyRenderType, Vertex *vertices, int32 numVertices, int &vleft, int &vright, int &vtop, int &vbottom);
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
2020-11-29 20:21:52 +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);
public:
Renderer(TwinEEngine *engine);
int16 projPosXScreen = 0; // fullRedrawVar1
int16 projPosYScreen = 0; // fullRedrawVar2
int16 projPosZScreen = 0; // fullRedrawVar3
int16 projPosX = 0;
int16 projPosY = 0;
int16 projPosZ = 0;
int32 orthoProjX = 0; // setSomethingVar1
int32 orthoProjY = 0; // setSomethingVar2
int32 orthoProjZ = 0; // setSomethingVar2
int32 destX = 0;
int32 destY = 0;
int32 destZ = 0;
const int16 * const shadeAngleTab3;
int16 vertexCoordinates[193] {0};
void setLightVector(int32 angleX, int32 angleY, int32 angleZ);
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);
int32 projectPositionOnScreen(int32 cX, int32 cY, int32 cZ);
2020-10-30 20:29:10 +01:00
void setCameraPosition(int32 x, int32 y, int32 cX, int32 cY, int32 cZ);
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);
void setBaseRotation(int32 x, int32 y, int32 z);
void setOrthoProjection(int32 x, int32 y, int32 z);
2020-12-13 17:43:01 +01:00
int32 renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const uint8 *bodyPtr);
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);
void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const uint8 *bodyPtr);
2020-12-13 17:43:01 +01:00
void renderInventoryItem(int32 x, int32 y, const uint8 *bodyPtr, int32 angle, int32 param);
};
} // namespace TwinE
2020-10-14 14:20:38 +02:00
#endif