scummvm/engines/twine/renderer/renderer.h

281 lines
9.7 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
2021-03-27 20:32:09 +01:00
#ifndef TWINE_RENDERER_RENDERER_H
#define TWINE_RENDERER_RENDERER_H
2020-10-14 14:20:38 +02:00
#include "common/endian.h"
#include "common/rect.h"
#include "common/scummsys.h"
#include "twine/parser/body.h"
#include "twine/twine.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
2021-03-18 20:17:50 +01:00
#define POLYGONTYPE_UNKNOWN 9
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;
int16 top = 0;
int16 bottom = 0;
2020-11-29 14:26:56 +01:00
// followed by Vertex array
};
2021-03-17 18:59:52 +01:00
struct IMatrix3x3 {
2021-03-17 18:56:19 +01:00
IVec3 row1;
IVec3 row2;
IVec3 row3;
2020-11-29 22:04:29 +01:00
};
2021-03-17 18:59:52 +01:00
inline IMatrix3x3 operator*(const IMatrix3x3 &matrix, const IVec3 &vec) {
IMatrix3x3 out;
2021-03-27 20:06:10 +01:00
out.row1.x = matrix.row1.x * vec.x;
out.row1.y = matrix.row1.y * vec.x;
out.row1.z = matrix.row1.z * vec.x;
2020-12-14 11:02:13 +01:00
2021-03-27 20:06:10 +01:00
out.row2.x = matrix.row2.x * vec.y;
out.row2.y = matrix.row2.y * vec.y;
out.row2.z = matrix.row2.z * vec.y;
2020-12-14 11:02:13 +01:00
2021-03-27 20:06:10 +01:00
out.row3.x = matrix.row3.x * vec.z;
out.row3.y = matrix.row3.y * vec.z;
out.row3.z = matrix.row3.z * vec.z;
2020-12-14 11:02:13 +01:00
return out;
}
class Renderer {
private:
TwinEEngine *_engine;
2020-10-14 14:20:38 +02:00
struct RenderCommand {
int16 depth = 0;
int16 renderType = 0;
2021-03-17 20:22:56 +01:00
/**
* Pointer to the command data
* @sa renderCoordinatesBuffer
* @sa CmdRenderLine
* @sa CmdRenderSphere
* @sa CmdRenderPolygon
2021-03-17 20:22:56 +01:00
*/
uint8 *dataPtr = nullptr;
2020-10-21 11:23:09 +02:00
};
2020-10-14 14:20:38 +02:00
2021-03-17 20:22:56 +01:00
/**
* @brief A render command payload for drawing a line
*
* @sa RenderCommand
*/
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;
};
2021-03-17 20:22:56 +01:00
/**
* @brief A render command payload for drawing a sphere
*
* @sa RenderCommand
*/
2020-11-29 18:03:12 +01:00
struct CmdRenderSphere {
int8 colorIndex = 0;
2021-08-05 06:00:08 +02:00
int16 radius = 0;
2020-11-29 18:03:12 +01:00
int16 x = 0;
int16 y = 0;
2021-08-05 06:00:08 +02:00
int16 z = 0;
2020-11-29 18:03:12 +01:00
};
2020-11-29 20:21:52 +01:00
struct ModelData {
2021-03-26 21:20:52 +01:00
I16Vec3 computedPoints[800];
I16Vec3 flattenPoints[800];
int16 shadeTable[500]{0};
2020-11-29 20:21:52 +01:00
};
ModelData _modelData;
bool renderAnimatedModel(ModelData *modelData, const BodyData &bodyData, RenderCommand *renderCmds, const IVec3 &angleVec, const IVec3 &renderPos, Common::Rect &modelRect);
2020-11-27 23:37:13 +01:00
void circleFill(int32 x, int32 y, int32 radius, uint8 color);
bool renderModelElements(int32 numOfPrimitives, const BodyData &bodyData, RenderCommand **renderCmds, ModelData *modelData, Common::Rect &modelRect);
const IVec3 &getCameraAnglePositions(int32 x, int32 y, int32 z);
inline const IVec3 &getCameraAnglePositions(const IVec3 &vec) {
return getCameraAnglePositions(vec.x, vec.y, vec.z);
}
2021-03-18 20:45:13 +01:00
void applyRotation(IMatrix3x3 *targetMatrix, const IMatrix3x3 *currentMatrix, const IVec3 &angleVec);
2021-03-27 08:57:54 +01:00
void applyPointsRotation(const Common::Array<BodyVertex>& vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *rotationMatrix);
void processRotatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex>& vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData);
void applyPointsTranslation(const Common::Array<BodyVertex>& vertices, int32 firstPoint, int32 numPoints, I16Vec3 *destPoints, const IMatrix3x3 *translationMatrix, const IVec3 &angleVec);
void processTranslatedElement(IMatrix3x3 *targetMatrix, const Common::Array<BodyVertex>& vertices, int32 rotX, int32 rotY, int32 rotZ, const BodyBone &bone, ModelData *modelData);
const IVec3 &translateGroup(int32 x, int32 y, int32 z);
2020-10-14 14:20:38 +02:00
2021-03-19 14:45:20 +01:00
IVec3 _baseTransPos;
2021-03-19 15:27:11 +01:00
IVec3 _orthoProjPos;
2020-10-14 14:20:38 +02:00
2021-03-19 14:45:20 +01:00
int32 _cameraDepthOffset = 0;
int32 _cameraScaleY = 0;
int32 _cameraScaleZ = 0;
2021-03-19 14:45:20 +01:00
IMatrix3x3 _baseMatrix;
IMatrix3x3 _matricesTable[30 + 1];
IMatrix3x3 _shadeMatrix;
IVec3 _lightPos;
2021-07-31 15:55:37 +02:00
IVec3 _baseRotPos;
RenderCommand _renderCmds[1000];
2021-03-17 20:22:56 +01:00
/**
* @brief Raw buffer for holding the render commands. This is a type followed by the command data
* that is needed to render the primitive.
*/
2021-03-19 14:45:20 +01:00
uint8 _renderCoordinatesBuffer[10000]{0};
int32 _polyTabSize = 0;
int16 *_polyTab = nullptr;
int16 *_polyTab2 = nullptr;
2021-02-28 16:09:23 +01:00
int16* _holomap_polytab_1_1 = nullptr;
int16* _holomap_polytab_1_2 = nullptr;
int16* _holomap_polytab_1_3 = nullptr;
int16* _holomap_polytab_2_3 = nullptr;
int16* _holomap_polytab_2_2 = nullptr;
int16* _holomap_polytab_2_1 = nullptr;
int16* _holomap_polytab_1_2_ptr = nullptr;
int16* _holomap_polytab_1_3_ptr = nullptr;
2021-03-19 14:45:20 +01:00
bool _isUsingOrthoProjection = false;
2020-10-27 17:30:15 +01:00
void renderPolygonsCopper(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsBopper(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsFlat(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsTele(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsTras(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsTrame(int vtop, int32 vsize, uint8 color) const;
void renderPolygonsGouraud(int vtop, int32 vsize) const;
void renderPolygonsDither(int vtop, int32 vsize) const;
void renderPolygonsMarble(int vtop, int32 vsize, uint8 color) const;
void computePolygons(int16 polyRenderType, const Vertex *vertices, int32 numVertices);
const RenderCommand *depthSortRenderCommands(int32 numOfPrimitives);
2021-03-27 08:57:54 +01:00
uint8 *preparePolygons(const Common::Array<BodyPolygon>& polygons, 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(const Common::Array<BodyLine>& lines, int32 &numOfPrimitives, RenderCommand **renderCmds, uint8 *renderBufferPtr, ModelData *modelData);
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
public:
Renderer(TwinEEngine *engine);
~Renderer();
void init(int32 w, int32 h);
2021-07-31 15:44:15 +02:00
IVec3 _projPos;
IVec3 _destPos;
2021-07-31 16:16:13 +02:00
2021-07-31 15:55:37 +02:00
void setBaseRotationPos(int32 x, int32 y, int32 z);
2021-03-17 00:17:51 +01:00
IVec3 getHolomapRotation(const int32 angleX, const int32 angleY, const int32 angleZ) const;
void setLightVector(int32 angleX, int32 angleY, int32 angleZ);
const IVec3 &getBaseRotationPosition(int32 x, int32 y, int32 z);
inline const IVec3 &getBaseRotationPosition(const IVec3& vec) {
return getBaseRotationPosition(vec.x, vec.y, vec.z);
}
void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices, int vtop, int vbottom);
inline IVec3 &projectPositionOnScreen(const IVec3& pos) {
return projectPositionOnScreen(pos.x, pos.y, pos.z);
}
IVec3 &projectPositionOnScreen(int32 cX, int32 cY, int32 cZ);
inline const IVec3 &projectXYPositionOnScreen(const IVec3& pos) {
return projectXYPositionOnScreen(pos.x, pos.y, pos.z);
}
const IVec3 &projectXYPositionOnScreen(int32 x,int32 y,int32 z);
2021-01-26 01:04:39 +01:00
void setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleY, int32 scaleZ);
void setCameraAngle(int32 transPosX, int32 transPosY, int32 transPosZ, int32 rotPosX, int32 rotPosY, int32 rotPosZ, int32 param6);
const IVec3 &updateCameraAnglePositions(int zShift = 0);
2020-10-30 20:29:10 +01:00
void setBaseTranslation(int32 x, int32 y, int32 z);
const IVec3 &setBaseRotation(int32 x, int32 y, int32 z, bool transpose = false);
inline const IVec3 &setBaseRotation(const IVec3 &rot, bool transpose = false) {
return setBaseRotation(rot.x, rot.y, rot.z, transpose);
}
2020-10-30 20:29:10 +01:00
void setOrthoProjection(int32 x, int32 y, int32 z);
bool renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const BodyData &bodyData, Common::Rect &modelRect);
inline bool renderIsoModel(const IVec3 &pos, int32 angleX, int32 angleY, int32 angleZ, const BodyData &bodyData, Common::Rect &modelRect) {
return renderIsoModel(pos.x, pos.y, pos.z, angleX, angleY, angleZ, bodyData, modelRect);
}
2021-02-25 05:53:09 +01:00
/**
* @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 BodyData &bodyData, ActorMoveStruct &move);
2021-02-25 05:53:09 +01:00
/**
* @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 BodyData &bodyData, ActorMoveStruct &move);
2021-03-27 08:57:54 +01:00
void renderInventoryItem(int32 x, int32 y, const BodyData &bodyData, int32 angle, int32 param);
2021-08-08 10:28:41 +02:00
void renderHolomapVertices(const Vertex vertexCoordinates[3], const Vertex vertexCoordinates2[3]);
};
2021-07-31 15:55:37 +02:00
inline void Renderer::setBaseRotationPos(int32 x, int32 y, int32 z) {
_baseRotPos.x = x;
_baseRotPos.y = y;
_baseRotPos.z = z;
}
} // namespace TwinE
2020-10-14 14:20:38 +02:00
#endif