1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-01-17 21:09:00 +01:00

#370 3DO data optimizations, save one memory page for level data, store room poly clipping flags in vertex.z, reduce vertex buffer size

This commit is contained in:
XProger 2021-11-13 02:55:49 +03:00
parent 9bff9948f1
commit 9ec2c8e586
7 changed files with 218 additions and 259 deletions

View File

@ -383,6 +383,7 @@ void Camera::update()
void Camera::prepareFrustum()
{
#ifndef MODEHW
matrixSetIdentity();
matrixRotateYXZ(angle.x, angle.y, angle.z);
@ -425,16 +426,19 @@ void Camera::prepareFrustum()
frustumBase.maxY += view.pos.y + 1024;
frustumBase.minZ += view.pos.z - 1024;
frustumBase.maxZ += view.pos.z + 1024;
#endif
}
void Camera::updateFrustum(int32 offsetX, int32 offsetY, int32 offsetZ)
{
#ifndef MODEHW
frustumAABB.minX = frustumBase.minX - offsetX;
frustumAABB.maxX = frustumBase.maxX - offsetX;
frustumAABB.minY = frustumBase.minY - offsetY;
frustumAABB.maxY = frustumBase.maxY - offsetY;
frustumAABB.minZ = frustumBase.minZ - offsetZ;
frustumAABB.maxZ = frustumBase.maxZ - offsetZ;
#endif
}
void Camera::toCombat()

View File

@ -1,13 +1,16 @@
#include "common.h"
uint32 keys;
AABBi frustumAABB;
RectMinMax viewport;
vec3i cameraViewPos;
vec3i cameraViewOffset;
Matrix matrixStack[MAX_MATRICES];
Matrix* matrixPtr = matrixStack;
#ifndef MODEHW
AABBi frustumAABB;
#endif
const FloorData* gLastFloorData;
FloorData gLastFloorSlant;
TargetInfo tinfo;

View File

@ -37,7 +37,7 @@
#include <mem.h>
#elif defined(__3DO__)
#define MODEHW
#define USE_DIV_TABLE // 4k of DRAM
//#define USE_DIV_TABLE // 4k of DRAM
#define CPU_BIG_ENDIAN
#define BLOCK_SIZE_DRAM (32 * 1024)
@ -47,7 +47,7 @@
#define SND_BUFFER_SIZE (4 * BLOCK_SIZE_CD)
#define SND_BUFFERS 4
#define MAX_RAM_LVL (BLOCK_SIZE_DRAM * 30) // 38 for LEVEL10C! >_<
#define MAX_RAM_LVL (BLOCK_SIZE_DRAM * 31) // 35 for LEVEL10C! >_<
#define MAX_RAM_TEX (BLOCK_SIZE_VRAM * 44)
#define MAX_RAM_CEL (MAX_FACES * sizeof(CCB))
#define MAX_RAM_SND (SND_BUFFERS * SND_BUFFER_SIZE)
@ -401,6 +401,12 @@ extern int32 fps;
#define SND_MAX 127
#endif
#ifdef __3DO__
#define MAX_VERTICES (1024 + 32) // for mesh (max = LEVEL10A room:58)
#else
#define MAX_VERTICES (5*1024) // for frame
#endif
#define MAX_UPDATE_FRAMES 10
#define MAX_PLAYERS 1 // TODO 2 players for non-potato platforms
@ -413,7 +419,6 @@ extern int32 fps;
#define MAX_STATIC_MESHES 50
#define MAX_CAMERAS 16
#define MAX_BOXES 1024
#define MAX_VERTICES (3*1024)
#define MAX_TEXTURES 1536
#define MAX_FACES 1920
#define MAX_ROOM_LIST 16
@ -952,10 +957,7 @@ struct Texture
#ifdef __3DO__
uint8* data;
uint8* plut;
uint8 wShift;
uint8 hShift;
uint16 color;
uint32 _unused;
uint32 shift;
#else
uint16 attribute;
uint16 tile;
@ -2031,7 +2033,6 @@ struct IMA_STATE
// renderer internal
extern uint32 keys;
extern AABBi frustumAABB;
extern RectMinMax viewport;
extern vec3i cameraViewPos;
extern vec3i cameraViewOffset;
@ -2040,6 +2041,10 @@ extern Matrix matrixStack[MAX_MATRICES];
extern int32 gVerticesCount;
extern int32 gFacesCount;
#ifndef MODEHW
extern AABBi frustumAABB;
#endif
extern SaveGame gSaveGame;
extern Settings gSettings;
extern int32 gCurTrack;

View File

@ -473,13 +473,13 @@ Room** Room::addVisibleRoom(Room** list)
{
int32 axis = 0;
int32 x = (portal->v[0].x - cx) << F16_SHIFT;
if (x > 0) axis |= (2 << 0);
if (x >= 0) axis |= (2 << 0);
if (x < 0) axis |= (1 << 0);
int32 y = (portal->v[0].y - cy) << F16_SHIFT;
if (y > 0) axis |= (2 << 2);
if (y >= 0) axis |= (2 << 2);
if (y < 0) axis |= (1 << 2);
int32 z = (portal->v[0].z - cz) << F16_SHIFT;
if (z > 0) axis |= (2 << 4);
if (z >= 0) axis |= (2 << 4);
if (z < 0) axis |= (1 << 4);
vis[i] = (portal->normalMask & axis);

View File

@ -379,7 +379,7 @@ updateTime = osGetSystemTimeMS() - updateTime;
lastFrame = frame;
screenItem = screen.sc_BitmapItems[screenPage];
screenItem = screen.sc_ScreenItems[screenPage];
int32 renderTime = osGetSystemTimeMS();
game.render();

View File

@ -2,7 +2,7 @@
struct Vertex
{
int32 x, y, z;
int32 x, y, z; // for rooms z = (depth << CLIP_SHIFT) | ClipFlags
};
uint16* gPalette;
@ -18,10 +18,7 @@ int32 gVerticesCount;
int32 gFacesCount;
Vertex gVertices[MAX_VERTICES];
uint8 gClip[MAX_VERTICES];
Vertex* gVerticesBase = NULL;
uint8* gClipBase = NULL;
Face* gFaces; // MAX_FACES
Face* otFacesHead[OT_SIZE];
@ -121,13 +118,11 @@ void renderInit()
}
gVerticesBase = gVertices;
gClipBase = gClip;
}
X_INLINE void resetBase()
{
gVerticesBase = gVertices + gVerticesCount;
gClipBase = gClip + gVerticesCount;
}
void setViewport(const RectMinMax &vp)
@ -176,12 +171,23 @@ X_INLINE bool checkBackface(const Vertex *a, const Vertex *b, const Vertex *c)
(c->x - a->x) * (b->y - a->y) <= 0;
}
enum ClipFlags {
CLIP_SHIFT = 8,
CLIP_MASK = (1 << CLIP_SHIFT) - 1,
CLIP_LEFT = 1 << 0,
CLIP_RIGHT = 1 << 1,
CLIP_TOP = 1 << 2,
CLIP_BOTTOM = 1 << 3,
CLIP_FAR = 1 << 4,
CLIP_NEAR = 1 << 5
};
X_INLINE int32 classify(const Vertex* v, int32 x0, int32 y0, int32 x1, int32 y1)
{
return (v->x < x0 ? 1 : 0) |
(v->x > x1 ? 2 : 0) |
(v->y < y0 ? 4 : 0) |
(v->y > y1 ? 8 : 0);
return (v->x < x0 ? CLIP_LEFT : 0) |
(v->x > x1 ? CLIP_RIGHT : 0) |
(v->y < y0 ? CLIP_TOP : 0) |
(v->y > y1 ? CLIP_BOTTOM : 0);
}
void transform(vec3i* points, int32 count)
@ -286,18 +292,15 @@ void transformRoom(const RoomVertex* vertices, int32 vCount, bool underwater)
int32 y1 = viewportRel.y1;
res = gVerticesBase;
uint8* clip = gClipBase;
for (int32 i = 0; i < vCount; i++, res++, clip++)
for (int32 i = 0; i < vCount; i++, res++)
{
if (res->z < (VIEW_MIN_F >> FIXED_SHIFT)) {
res->z = (VIEW_MIN_F >> FIXED_SHIFT);
*clip = 32;
res->z = ((VIEW_MIN_F >> FIXED_SHIFT) << CLIP_SHIFT) | CLIP_NEAR;
} else if (res->z >= (VIEW_MAX_F >> FIXED_SHIFT)) {
res->z = (VIEW_MAX_F >> FIXED_SHIFT);
*clip = 16;
res->z = ((VIEW_MAX_F >> FIXED_SHIFT) << CLIP_SHIFT) | CLIP_FAR;
} else {
*clip = classify(res, x0, y0, x1, y1);
res->z = (res->z << CLIP_SHIFT) | classify(res, x0, y0, x1, y1);
}
}
@ -319,15 +322,13 @@ void transformMesh(const MeshVertex* vertices, int32 vCount, const uint16* vInte
int32 cy = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e01) >> DOT_SHIFT; // dot(pos, up)
int32 cz = Dot3_F16(*(vec3f16*)&m.e03, *(vec3f16*)&m.e02) >> DOT_SHIFT; // dot(pos, dir)
Vertex* res = gVerticesBase;
uint32 *v32 = (uint32*)vertices;
Vertex* res = gVerticesBase;
for (int32 i = 0; i < vCount; i++, res++)
{
// << F16_SHIFT should be already applied
uint32 p = *v32++;
//p += cxy;
res->x = cx + int16(p);
res->y = cy + int16(p >> 16);
p = *v32++;
@ -339,10 +340,10 @@ void transformMesh(const MeshVertex* vertices, int32 vCount, const uint16* vInte
gVerticesCount += vCount;
}
#define DEPTH_T_AVG() ((v0->z + v1->z + v2->z + v2->z) >> (2 + OT_SHIFT))
#define DEPTH_T_MAX() (X_MAX(v0->z, X_MAX(v1->z, v2->z)) >> OT_SHIFT)
#define DEPTH_Q_AVG() ((v0->z + v1->z + v2->z + v3->z) >> (2 + OT_SHIFT))
#define DEPTH_Q_MAX() (X_MAX(v0->z, X_MAX(v1->z, X_MAX(v2->z, v3->z))) >> OT_SHIFT)
#define DEPTH_T_AVG(z0,z1,z2) ((z0 + z1 + z2 + z2) >> (2 + OT_SHIFT))
#define DEPTH_Q_AVG(z0,z1,z2,z3) ((z0 + z1 + z2 + z3) >> (2 + OT_SHIFT))
#define DEPTH_T_MAX(z0,z1,z2) (X_MAX(z0, X_MAX(z1, z2)) >> (CLIP_SHIFT + OT_SHIFT))
#define DEPTH_Q_MAX(z0,z1,z2,z3) (X_MAX(z0, X_MAX(z1, X_MAX(z2, z3))) >> (CLIP_SHIFT + OT_SHIFT))
X_INLINE Face* faceAdd(int32 depth)
{
@ -407,54 +408,8 @@ X_INLINE void ccbSetColor(uint32 flags, Face* face)
face->ccb_SourcePtr = (CelData*)&gPalette[flags & 0xFF];
}
X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
X_INLINE void ccbMap4(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, const Vertex* v3, uint32 shift)
{
uint32 i01 = ((uint32*)indices)[0];
uint32 i23 = ((uint32*)indices)[1];
uint32 i0 = (i01 >> 16);
uint32 i1 = (i01 & 0xFFFF);
uint32 i2 = (i23 >> 16);
uint32 i3 = (i23 & 0xFFFF);
uint8 c0 = gClipBase[i0];
uint8 c1 = gClipBase[i1];
uint8 c2 = gClipBase[i2];
uint8 c3 = gClipBase[i3];
if (c0 & c1 & c2 & c3)
return;
if (c0 == 32 || c1 == 32 || c2 == 32 || c3 == 32)
return;
const Vertex* v0 = gVerticesBase + i0;
const Vertex* v1 = gVerticesBase + i1;
const Vertex* v2 = gVerticesBase + i2;
const Vertex* v3 = gVerticesBase + i3;
if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW))
return;
int32 depth = DEPTH_Q_MAX();
Face* f = faceAdd(depth);
uint32 intensity = (flags >> (FACE_MIP_SHIFT + FACE_MIP_SHIFT)) & 0xFF;
if (depth > (FOG_MIN >> OT_SHIFT)) {
intensity += (depth - (FOG_MIN >> OT_SHIFT)) >> 1;
intensity = X_MIN(intensity, 255);
}
f->ccb_PIXC = shadeTable[intensity >> 3];
uint32 texIndex = flags;
if (depth > (MIP_DIST >> OT_SHIFT)) {
texIndex >>= FACE_MIP_SHIFT;
}
const Texture* texture = level.textures + (texIndex & FACE_TEXTURE);
ccbSetTexture(flags, f, texture);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
@ -464,8 +419,8 @@ X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
int32 x3 = v3->x;
int32 y3 = v3->y;
int32 ws = texture->wShift;
int32 hs = texture->hShift;
uint32 ws = shift & 0xFF;
uint32 hs = shift >> 8;
int32 hdx0 = (x1 - x0) << ws;
int32 hdy0 = (y1 - y0) << ws;
@ -487,6 +442,87 @@ X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
f->ccb_HDDY = (hdy1 - hdy0) >> hs;
}
X_INLINE void ccbMap3(Face* f, const Vertex* v0, const Vertex* v1, const Vertex* v2, uint32 shift)
{
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
uint32 ws = shift & 0xFF;
uint32 hs = shift >> 8;
int32 hdx0 = (x1 - x0) << ws;
int32 hdy0 = (y1 - y0) << ws;
int32 vdx0 = (x2 - x0) << hs;
int32 vdy0 = (y2 - y0) << hs;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = -hdx0 >> hs;
f->ccb_HDDY = -hdy0 >> hs;
}
X_INLINE void faceAddRoomQuad(uint32 flags, const Index* indices)
{
uint32 i01 = ((uint32*)indices)[0];
uint32 i23 = ((uint32*)indices)[1];
uint32 i0 = (i01 >> 16);
uint32 i1 = (i01 & 0xFFFF);
uint32 i2 = (i23 >> 16);
uint32 i3 = (i23 & 0xFFFF);
const Vertex* v0 = gVerticesBase + i0;
const Vertex* v1 = gVerticesBase + i1;
const Vertex* v2 = gVerticesBase + i2;
const Vertex* v3 = gVerticesBase + i3;
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
uint32 c3 = v3->z;
if ((c0 & c1 & c2 & c3) & CLIP_MASK)
return;
if ((c0 & CLIP_NEAR) || (c1 & CLIP_NEAR) || (c2 & CLIP_NEAR) || (c3 & CLIP_NEAR))
return;
int32 depth = DEPTH_Q_MAX(c0, c1, c2, c3);
if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW))
return;
Face* f = faceAdd(depth);
uint32 intensity = (flags >> (FACE_MIP_SHIFT + FACE_MIP_SHIFT)) & 0xFF;
if (depth > (FOG_MIN >> OT_SHIFT)) {
intensity += (depth - (FOG_MIN >> OT_SHIFT)) >> 1;
intensity = X_MIN(intensity, 255);
}
f->ccb_PIXC = shadeTable[intensity >> 3];
uint32 texIndex = flags;
if (depth > (MIP_DIST >> OT_SHIFT)) {
texIndex >>= FACE_MIP_SHIFT;
}
const Texture* texture = level.textures + (texIndex & FACE_TEXTURE);
ccbSetTexture(flags, f, texture);
ccbMap4(f, v0, v1, v2, v3, texture->shift);
}
X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices)
{
uint32 i01 = ((uint32*)indices)[0];
@ -496,24 +532,24 @@ X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices)
uint32 i1 = (i01 & 0xFFFF);
uint32 i2 = (i23 >> 16);
uint8 c0 = gClipBase[i0];
uint8 c1 = gClipBase[i1];
uint8 c2 = gClipBase[i2];
if (c0 & c1 & c2)
return;
if (c0 == 32 || c1 == 32 || c2 == 32)
return;
const Vertex* v0 = gVerticesBase + i0;
const Vertex* v1 = gVerticesBase + i1;
const Vertex* v2 = gVerticesBase + i2;
if (checkBackface(v0, v1, v2))
uint32 c0 = v0->z;
uint32 c1 = v1->z;
uint32 c2 = v2->z;
if ((c0 & c1 & c2) & CLIP_MASK)
return;
int32 depth = DEPTH_T_MAX();
if ((c0 & CLIP_NEAR) || (c1 & CLIP_NEAR) || (c2 & CLIP_NEAR))
return;
int32 depth = DEPTH_T_MAX(c0, c1, c2);
if (checkBackface(v0, v1, v2) == !(flags & FACE_CCW))
return;
Face* f = faceAdd(depth);
@ -532,32 +568,7 @@ X_INLINE void faceAddRoomTriangle(uint32 flags, const Index* indices)
const Texture* texture = level.textures + (texIndex & FACE_TEXTURE);
ccbSetTexture(flags, f, texture);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 ws = texture->wShift;
int32 hs = texture->hShift;
int32 hdx0 = (x1 - x0) << ws;
int32 hdy0 = (y1 - y0) << ws;
int32 vdx0 = (x2 - x0) << hs;
int32 vdy0 = (y2 - y0) << hs;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = -hdx0 >> hs;
f->ccb_HDDY = -hdy0 >> hs;
ccbMap3(f, v0, v1, v2, texture->shift);
}
X_INLINE void faceAddMeshQuad(uint32 flags, uint32 indices, uint32 shade)
@ -575,7 +586,7 @@ X_INLINE void faceAddMeshQuad(uint32 flags, uint32 indices, uint32 shade)
if (checkBackface(v0, v1, v3) == !(flags & FACE_CCW)) // TODO (hdx0 * vdy0 - vdx0 * hdy0) <= 0
return;
int32 depth = DEPTH_Q_AVG();
int32 depth = DEPTH_Q_AVG(v0->z, v1->z, v2->z, v3->z);
Face* f = faceAdd(depth);
f->ccb_PIXC = shade;
@ -583,36 +594,7 @@ X_INLINE void faceAddMeshQuad(uint32 flags, uint32 indices, uint32 shade)
const Texture* texture = level.textures + (flags & FACE_TEXTURE);
ccbSetTexture(flags, f, texture);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 x3 = v3->x;
int32 y3 = v3->y;
int32 ws = texture->wShift;
int32 hs = texture->hShift;
int32 hdx0 = (x1 - x0) << ws;
int32 hdy0 = (y1 - y0) << ws;
int32 hdx1 = (x2 - x3) << ws;
int32 hdy1 = (y2 - y3) << ws;
int32 vdx0 = (x3 - x0) << hs;
int32 vdy0 = (y3 - y0) << hs;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = (hdx1 - hdx0) >> hs;
f->ccb_HDDY = (hdy1 - hdy0) >> hs;
ccbMap4(f, v0, v1, v2, v3, texture->shift);
}
X_INLINE void faceAddMeshTriangle(uint32 flags, uint32 indices, uint32 shade)
@ -628,7 +610,7 @@ X_INLINE void faceAddMeshTriangle(uint32 flags, uint32 indices, uint32 shade)
if (checkBackface(v0, v1, v2))
return;
int32 depth = DEPTH_T_AVG();
int32 depth = DEPTH_T_AVG(v0->z, v1->z, v2->z);
Face* f = faceAdd(depth);
f->ccb_PIXC = shade;
@ -636,32 +618,7 @@ X_INLINE void faceAddMeshTriangle(uint32 flags, uint32 indices, uint32 shade)
const Texture* texture = level.textures + (flags & FACE_TEXTURE);
ccbSetTexture(flags, f, texture);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 ws = texture->wShift;
int32 hs = texture->hShift;
int32 hdx0 = (x1 - x0) << ws;
int32 hdy0 = (y1 - y0) << ws;
int32 vdx0 = (x2 - x0) << hs;
int32 vdy0 = (y2 - y0) << hs;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
hs = 16 - hs;
f->ccb_HDDX = -hdx0 >> hs;
f->ccb_HDDY = -hdy0 >> hs;
ccbMap3(f, v0, v1, v2, texture->shift);
}
X_INLINE void faceAddMeshQuadFlat(uint32 flags, uint32 indices, uint32 shade)
@ -679,39 +636,14 @@ X_INLINE void faceAddMeshQuadFlat(uint32 flags, uint32 indices, uint32 shade)
if (checkBackface(v0, v1, v3))
return;
int32 depth = DEPTH_Q_AVG();
int32 depth = DEPTH_Q_AVG(v0->z, v1->z, v2->z, v3->z);
Face* f = faceAdd(depth);
f->ccb_PIXC = shade;
ccbSetColor(flags, f);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 x3 = v3->x;
int32 y3 = v3->y;
int32 hdx0 = (x1 - x0) << 20;
int32 hdy0 = (y1 - y0) << 20;
int32 hdx1 = (x2 - x3) << 20;
int32 hdy1 = (y2 - y3) << 20;
int32 vdx0 = (x3 - x0) << 16;
int32 vdy0 = (y3 - y0) << 16;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
f->ccb_HDDX = (hdx1 - hdx0);
f->ccb_HDDY = (hdy1 - hdy0);
ccbMap4(f, v0, v1, v2, v3, 20 | (16 << 8));
}
X_INLINE void faceAddMeshTriangleFlat(uint32 flags, uint32 indices, uint32 shade)
@ -727,35 +659,14 @@ X_INLINE void faceAddMeshTriangleFlat(uint32 flags, uint32 indices, uint32 shade
if (checkBackface(v0, v1, v2))
return;
int32 depth = DEPTH_T_AVG();
int32 depth = DEPTH_T_AVG(v0->z, v1->z, v2->z);
Face* f = faceAdd(depth);
f->ccb_PIXC = shade;
ccbSetColor(flags, f);
int32 x0 = v0->x;
int32 y0 = v0->y;
int32 x1 = v1->x;
int32 y1 = v1->y;
int32 x2 = v2->x;
int32 y2 = v2->y;
int32 hdx0 = (x1 - x0) << 20;
int32 hdy0 = (y1 - y0) << 20;
int32 vdx0 = (x2 - x0) << 16;
int32 vdy0 = (y2 - y0) << 16;
f->ccb_HDX = hdx0;
f->ccb_HDY = hdy0;
f->ccb_VDX = vdx0;
f->ccb_VDY = vdy0;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
f->ccb_HDDX = -hdx0;
f->ccb_HDDY = -hdy0;
ccbMap3(f, v0, v1, v2, 20 | (16 << 8));
}
void faceAddShadow(int32 x, int32 z, int32 sx, int32 sz)
@ -784,6 +695,8 @@ void faceAddShadow(int32 x, int32 z, int32 sx, int32 sz)
faceAddMeshQuadFlat(0, (0 | (1 << 8) | (2 << 16) | (7 << 24)), SHADE_SHADOW);
faceAddMeshQuadFlat(0, (7 | (2 << 8) | (3 << 16) | (6 << 24)), SHADE_SHADOW);
faceAddMeshQuadFlat(0, (6 | (3 << 8) | (4 << 16) | (5 << 24)), SHADE_SHADOW);
gVerticesCount = 0;
}
void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index)
@ -839,10 +752,14 @@ void faceAddSprite(int32 vx, int32 vy, int32 vz, int32 vg, int32 index)
Texture* texture = level.textures + sprite->texture;
ccbSetTexture(0, f, texture);
f->ccb_HDX = (x1 - x0) << texture->wShift;
uint32 shift = texture->shift;
uint32 ws = shift & 0xFF;
uint32 hs = shift >> 8;
f->ccb_HDX = (x1 - x0) << ws;
f->ccb_HDY = 0;
f->ccb_VDX = 0;
f->ccb_VDY = (y1 - y0) << texture->hShift;
f->ccb_VDY = (y1 - y0) << hs;
f->ccb_XPos = (x0 + (FRAME_WIDTH >> 1)) << 16;
f->ccb_YPos = (y0 + (FRAME_HEIGHT >> 1)) << 16;
@ -861,10 +778,14 @@ void faceAddGlyph(int32 vx, int32 vy, int32 index)
Texture* texture = level.textures + sprite->texture;
ccbSetTexture(0, f, texture);
f->ccb_HDX = (sprite->r - sprite->l) << texture->wShift;
uint32 shift = texture->shift;
uint32 ws = shift & 0xFF;
uint32 hs = shift >> 8;
f->ccb_HDX = (sprite->r - sprite->l) << ws;
f->ccb_HDY = 0;
f->ccb_VDX = 0;
f->ccb_VDY = (sprite->b - sprite->t) << texture->hShift;
f->ccb_VDY = (sprite->b - sprite->t) << hs;
f->ccb_XPos = (vx + sprite->l) << 16;
f->ccb_YPos = (vy + sprite->t) << 16;
@ -882,6 +803,8 @@ void faceAddRoom(const RoomQuad* quads, int32 qCount, const RoomTriangle* triang
for (int32 i = 0; i < tCount; i++, triangles++) {
faceAddRoomTriangle(triangles->flags, triangles->indices);
}
gVerticesCount = 0;
}
void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTriangle* tFaces, const MeshTriangle* ctFaces, int32 rCount, int32 crCount, int32 tCount, int32 ctCount)
@ -908,6 +831,8 @@ void faceAddMesh(const MeshQuad* rFaces, const MeshQuad* crFaces, const MeshTria
for (int32 i = 0; i < ctCount; i++) {
faceAddMeshTriangleFlat(ctFaces[i].flags, ctFaces[i].indices, shade);
}
gVerticesCount = 0;
}
void flush()
@ -945,7 +870,7 @@ void flush()
if (facesHead)
{
LAST_CEL(facesTail);
DrawCels(screenItem, facesHead);
DrawScreenCels(screenItem, facesHead);
UNLAST_CEL(facesTail);
}
}

View File

@ -2928,17 +2928,24 @@ struct LevelPC
int32 h;
uint16 flip;
int16 mip;
uint8* image;
void write(FileStream &f) const
{
uint32 unused = 0;
f.write(data);
f.write(plut);
f.write(wShift);
f.write(hShift);
f.write(color);
f.write(unused);
uint32 shift = wShift | (hShift << 8);
f.write(shift);
}
bool cmp(const Texture3DO &t)
{
if (wShift != t.wShift || hShift != t.hShift || plut != t.plut)
return false;
return memcmp(image, t.image, (1 << (20 - wShift)) * (1 << (16 - hShift)) / 2) == 0;
}
} textures3DO[MAX_TEXTURES];
int32 spritesBaseIndex;
@ -3117,6 +3124,8 @@ struct LevelPC
int32 mipIndex = objectTexturesCount;
int32 dupSize = 0;
for (int32 i = 0; i < objectTexturesCount; i++)
{
const LevelPC::ObjectTexture* objectTexture = objectTextures + i;
@ -3252,7 +3261,6 @@ struct LevelPC
if (w != wp || h != hp)
{
//stbir_resize_uint8((uint8*)bitmap32, w, h, 0, (uint8*)bitmap32_tmp, wp, hp, 0, 4);
stbir_resize_uint8_generic((uint8*)bitmap32, w, h, 0, (uint8*)bitmap32_tmp, wp, hp, 0, 4, 3, 0,
STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_COLORSPACE_LINEAR, NULL);
swap(bitmap32, bitmap32_tmp);
@ -3330,8 +3338,10 @@ struct LevelPC
}
{ // encode to 4-bit image
textures3DO[i].image = new uint8[rowBytes * h];
uint8* src = bitmap8;
uint8* dst = bitmap8_tmp;
uint8* dst = textures3DO[i].image;
for (int32 y = 0; y < h; y++)
{
for (int32 x = 0; x < rowBytes; x++, src += 2)
@ -3340,11 +3350,29 @@ struct LevelPC
}
}
textures3DO[i].data = 0;
/*
for (int32 j = 0; j < i; j++)
{
if (textures3DO[i].cmp(textures3DO[j]))
{
textures3DO[i].data = textures3DO[j].data;
//ASSERT((objectTextures[i].attribute & TEX_ATTR_MIPS) == (objectTextures[j].attribute & TEX_ATTR_MIPS));
dupSize += rowBytes * h;
break;
}
}
*/
// write image
textures3DO[i].data = f.getPos();
f.write(textures3DO[i].pre0);
f.write(textures3DO[i].pre1);
f.write(bitmap8_tmp, rowBytes * h);
if (!textures3DO[i].data) {
textures3DO[i].data = f.getPos();
f.write(textures3DO[i].pre0);
f.write(textures3DO[i].pre1);
f.write(textures3DO[i].image, rowBytes * h);
}
}
// generate mip level
@ -3364,7 +3392,6 @@ struct LevelPC
ASSERT(h > 0);
{
//stbir_resize_uint8((uint8*)bitmap32, w, h, 0, (uint8*)bitmap32_tmp, wp, hp, 0, 4);
stbir_resize_uint8_generic((uint8*)bitmap32, w << 1, h << 1, 0, (uint8*)bitmap32_tmp, w, h, 0, 4, 3, 0,
STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_COLORSPACE_LINEAR, NULL);
swap(bitmap32, bitmap32_tmp);
@ -3452,6 +3479,9 @@ struct LevelPC
objectTexturesCount = mipIndex;
printf("duplicate size: %d\n", dupSize);
// fix PLUT offsets
int32 plutsOffset = f.getPos();
for (int32 i = 0; i < objectTexturesCount; i++)
@ -3500,6 +3530,7 @@ struct LevelPC
void getSample(const char* base, const char* prefix, int32 id, int32 sub, uint8* buffer, int32 &size)
{
// 57 == 38?
size = 0;
char path[256];
@ -3850,7 +3881,7 @@ struct LevelPC
f.writeObj(floors, floorsCount);
header.meshData = f.align4();
#if 1
int32 mOffsets[2048];
for (int32 i = 0; i < 2048; i++) {
mOffsets[i] = -1;
@ -4039,13 +4070,6 @@ struct LevelPC
header.meshOffsets = f.align4();
f.write(mOffsets, meshOffsetsCount);
#else
f.write(meshData, meshDataSize);
header.meshOffsets = f.align4();
f.write(meshOffsets, meshOffsetsCount);
#endif
header.anims = f.align4();
f.writeObj(anims, animsCount);
@ -4315,8 +4339,6 @@ struct LevelPC
const char* levelNames[] = {
#if 0
"GYM",
"LEVEL1",
"LEVEL2",
#else
"TITLE",
"GYM",