diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ee2c63..8a323bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ option(PLUSH_BUILD_EXAMPLES "Build Plush Examples" ON) option(PLUSH_USE_ASAN "Use Address Sanitizer" OFF) set(PLUSH_MAX_LIGHTS "32" CACHE STRING "Maximum number of lights in a single render pass") set(PLUSH_MAX_TRIANGLES "16384" CACHE STRING "Maximum number of triangles in a single render pass") +set(PLUSH_MAX_VERTICES "49152" CACHE STRING "Maximum number of vertices in a single render pass") set(PLUSH_RESOURCE_ALIGNMENT "8" CACHE STRING "Byte alignment of resource memory allocations") # asan diff --git a/cmake/pl_conf.h.in b/cmake/pl_conf.h.in index ea50f51..f0587ba 100644 --- a/cmake/pl_conf.h.in +++ b/cmake/pl_conf.h.in @@ -26,6 +26,9 @@ approximately 8*PL_MAX_TRIANGLES bytes of memory. i.e. the default of #define PL_MAX_TRIANGLES (@PLUSH_MAX_TRIANGLES@) +/* Maximum number of vertices per scene */ +#define PL_MAX_VERTICES (@PLUSH_MAX_VERTICES@) + /* Byte alignment of resource memory allocations */ #define PL_RESOURCE_ALIGNMENT (@PLUSH_RESOURCE_ALIGNMENT@) diff --git a/include/plush/pl_types.h b/include/plush/pl_types.h index cfbdf4b..97e607c 100644 --- a/include/plush/pl_types.h +++ b/include/plush/pl_types.h @@ -35,6 +35,7 @@ typedef struct _pl_Texture { ** Material type. Create materials with plMatCreate(). */ typedef struct _pl_Face pl_Face; +typedef struct _pl_PrepFace pl_PrepFace; typedef struct _pl_Cam pl_Cam; typedef struct _pl_Mat { int32_t Ambient[3]; /* RGB of surface (0-255 is a good range) */ @@ -61,7 +62,7 @@ typedef struct _pl_Mat { uint16_t *_AddTable; /* Shading/Translucent/etc table */ uint8_t *_ReMapTable; /* Table to remap colors to palette */ uint8_t *_RequestedColors; /* _ColorsUsed colors, desired colors */ - void (*_PutFace)(pl_Cam *, pl_Face *); + void (*_PutFace)(pl_Cam *, pl_PrepFace *); /* Function that renders the triangle with this material */ } pl_Mat; @@ -71,13 +72,7 @@ typedef struct _pl_Mat { */ typedef struct _pl_Vertex { float x, y, z; /* Vertex coordinate (objectspace) */ - float xformedx, xformedy, xformedz; - /* Transformed vertex - coordinate (cameraspace) */ float nx, ny, nz; /* Unit vertex normal (objectspace) */ - float xformednx, xformedny, xformednz; - /* Transformed unit vertex normal - (cameraspace) */ } pl_Vertex; /* @@ -87,16 +82,11 @@ typedef struct _pl_Face { pl_Vertex *Vertices[3]; /* Vertices of triangle */ float nx, ny, nz; /* Normal of triangle (object space) */ pl_Mat *Material; /* Material of triangle */ - int32_t Scrx[3], Scry[3]; /* Projected screen coordinates - (12.20 fixed point) */ - float Scrz[3]; /* Projected 1/Z coordinates */ int32_t MappingU[3], MappingV[3]; /* 16.16 Texture mapping coordinates */ int32_t eMappingU[3], eMappingV[3]; /* 16.16 Environment map coordinates */ - float fShade; /* Flat intensity */ float sLighting; /* Face static lighting. Should usually be 0.0 */ - float Shades[3]; /* Vertex intensity */ float vsLighting[3]; /* Vertex static lighting. Should be 0.0 */ } pl_Face; @@ -183,6 +173,38 @@ typedef struct _pl_Cam { float *zBuffer; /* Z Buffer (NULL if none) */ } pl_Cam; +/* +** Prepared Vertex +*/ +typedef struct _pl_PrepVertex { + pl_Vertex *Vertex; /* Source vertex */ + float xformedx, xformedy, xformedz; /* Transformed vertex coordinate (cameraspace) */ + float xformednx, xformedny, xformednz; /* Transformed unit vertex normal (cameraspace) */ +} pl_PrepVertex; + +/* +** Prepared Face +*/ +typedef struct _pl_PrepFace { + pl_PrepVertex *Vertices[3]; /* Prepared vertices */ + pl_Face *Face; /* Source face */ + int32_t Scrx[3], Scry[3]; /* Projected screen coordinates (12.20 fixed point) */ + float Scrz[3]; /* Projected 1/Z coordinates */ + int32_t MappingU[3], MappingV[3]; /* 16.16 Texture mapping coordinates */ + int32_t eMappingU[3], eMappingV[3]; /* 16.16 Environment map coordinates */ + float Shades[3]; /* Vertex intensity */ + float zd; /* Z distance from camera (when using no zbuffer) */ + float fShade; /* Flat intensity */ +} pl_PrepFace; + +/* +** Prepared Light +*/ +typedef struct _pl_PrepLight { + pl_Light *light; + float l[3]; +} pl_PrepLight; + #ifdef __cplusplus } #endif diff --git a/include/plush/plush.h b/include/plush/plush.h index f0b2e06..5235026 100644 --- a/include/plush/plush.h +++ b/include/plush/plush.h @@ -392,46 +392,6 @@ int plObjEnumerate(pl_Obj *obj, int (*func)(pl_Obj *obj, void *user), void *user */ pl_Obj *plObjFind(pl_Obj *obj, const char *name); -/****************************************************************************** -** Frustum Clipping Functions (clip.c) -******************************************************************************/ - -/* - plClipSetFrustum() sets up the clipping frustum. - Parameters: - cam: a camera allocated with plCamCreate(). - Returns: - nothing - Notes: - Sets up the internal structures. - DO NOT CALL THIS ROUTINE FROM WITHIN A plRender*() block. -*/ -void plClipSetFrustum(pl_Cam *cam); - -/* - plClipRenderFace() renders a face and clips it to the frustum initialized - with plClipSetFrustum(). - Parameters: - face: the face to render - Returns: - nothing - Notes: this is used internally by plRender*(), so be careful. Kinda slow too. -*/ -void plClipRenderFace(pl_Face *face); - -/* - plClipNeeded() decides whether the face is in the frustum, intersecting - the frustum, or completely out of the frustum craeted with - plClipSetFrustum(). - Parameters: - face: the face to check - Returns: - 0: the face is out of the frustum, no drawing necessary - 1: the face is intersecting the frustum, splitting and drawing necessary - Notes: this is used internally by plRender*(), so be careful. Kinda slow too. -*/ -int32_t plClipNeeded(pl_Face *face); - /****************************************************************************** ** Light Handling Routines (light.c) ******************************************************************************/ @@ -978,15 +938,15 @@ void plTextPrintf(pl_Cam *cam, int32_t x, int32_t y, float z, ** Built-in Rasterizers ******************************************************************************/ -void plPF_SolidF(pl_Cam *, pl_Face *); -void plPF_SolidG(pl_Cam *, pl_Face *); -void plPF_TexF(pl_Cam *, pl_Face *); -void plPF_TexG(pl_Cam *, pl_Face *); -void plPF_TexEnv(pl_Cam *, pl_Face *); -void plPF_PTexF(pl_Cam *, pl_Face *); -void plPF_PTexG(pl_Cam *, pl_Face *); -void plPF_TransF(pl_Cam *, pl_Face *); -void plPF_TransG(pl_Cam *, pl_Face *); +void plPF_SolidF(pl_Cam *, pl_PrepFace *); +void plPF_SolidG(pl_Cam *, pl_PrepFace *); +void plPF_TexF(pl_Cam *, pl_PrepFace *); +void plPF_TexG(pl_Cam *, pl_PrepFace *); +void plPF_TexEnv(pl_Cam *, pl_PrepFace *); +void plPF_PTexF(pl_Cam *, pl_PrepFace *); +void plPF_PTexG(pl_Cam *, pl_PrepFace *); +void plPF_TransF(pl_Cam *, pl_PrepFace *); +void plPF_TransG(pl_Cam *, pl_PrepFace *); #ifdef __cplusplus } diff --git a/source/clip.c b/source/clip.c index fef941b..fc23d5b 100644 --- a/source/clip.c +++ b/source/clip.c @@ -12,7 +12,7 @@ Copyright (C) 2024-2025, erysdren (it/its) typedef struct { - pl_Vertex newVertices[8]; + pl_PrepVertex newVertices[8]; double Shades[8]; double MappingU[8]; double MappingV[8]; @@ -110,10 +110,10 @@ void plClipSetFrustum(pl_Cam *cam) { } -void plClipRenderFace(pl_Face *face) { +void plClipRenderFace(pl_PrepFace *face) { uint32_t k, a, w, numVerts; double tmp, tmp2; - pl_Face newface; + pl_PrepFace newface; for (a = 0; a < 3; a ++) { m_cl[0].newVertices[a] = *(face->Vertices[a]); @@ -133,7 +133,7 @@ void plClipRenderFace(pl_Face *face) { a++; } if (numVerts > 2) { - plMemCpy(&newface,face,sizeof(pl_Face)); + plMemCpy(&newface, face, sizeof(pl_PrepFace)); for (k = 2; k < numVerts; k ++) { newface.fShade = plMax(0,plMin(face->fShade,1)); for (a = 0; a < 3; a ++) { @@ -152,14 +152,14 @@ void plClipRenderFace(pl_Face *face) { newface.Scrx[a] = m_cx + ((int32_t)((tmp*(float) (1<<20)))); newface.Scry[a] = m_cy - ((int32_t)((tmp2*m_adj_asp*(float) (1<<20)))); } - newface.Material->_PutFace(m_cam,&newface); + newface.Face->Material->_PutFace(m_cam,&newface); plRender_TriStats[3] ++; } plRender_TriStats[2] ++; } } -int32_t plClipNeeded(pl_Face *face) { +int32_t plClipNeeded(pl_PrepFace *face) { double dr,dl,db,dt; double f; dr = (m_cam->ClipRight-m_cam->CenterX); diff --git a/source/make.c b/source/make.c index 2a95fc2..e7f4d1a 100644 --- a/source/make.c +++ b/source/make.c @@ -188,11 +188,13 @@ pl_Mdl *plMakeCylinder(float r, float h, uint32_t divr, bool captop, pl_Face *f; uint32_t i; double a, da; + int32_t *texcoords = NULL; if (divr < 3) divr = 3; mdl = plMdlCreate(divr*2+((divr==3)?0:(captop?1:0)+(capbottom?1:0)), divr*2+(divr==3 ? (captop ? 1 : 0) + (capbottom ? 1 : 0) : (captop ? divr : 0) + (capbottom ? divr : 0))); if (!mdl) return 0; + texcoords = plMalloc(mdl->NumVertices * sizeof(int32_t) * 2); a = 0.0; da = (2.0*PL_PI)/divr; v = mdl->Vertices; @@ -201,8 +203,8 @@ pl_Mdl *plMakeCylinder(float r, float h, uint32_t divr, bool captop, v->y = h/2.0f; v->x = (float) (r*plCos((double) a)); v->z = (float)(r*plSin(a)); - v->xformedx = (float) (32768.0 + (32768.0*plCos((double) a))); // temp - v->xformedy = (float) (32768.0 + (32768.0*plSin((double) a))); // use xf + texcoords[((v - mdl->Vertices) * 2) + 0] = (int32_t) (32768.0 + (32768.0*plCos((double) a))); // temp + texcoords[((v - mdl->Vertices) * 2) + 1] = (int32_t) (32768.0 + (32768.0*plSin((double) a))); // use xf v++; a += da; } @@ -212,8 +214,8 @@ pl_Mdl *plMakeCylinder(float r, float h, uint32_t divr, bool captop, v->y = -h/2.0f; v->x = (float) (r*plCos((double) a)); v->z = (float) (r*plSin(a)); - v->xformedx = (float) (32768.0 + (32768.0*plCos((double) a))); - v->xformedy = (float) (32768.0 + (32768.0*plSin((double) a))); + texcoords[((v - mdl->Vertices) * 2) + 0] = (int32_t) (32768.0 + (32768.0*plCos((double) a))); + texcoords[((v - mdl->Vertices) * 2) + 1] = (int32_t) (32768.0 + (32768.0*plSin((double) a))); v++; a += da; } if (captop && divr != 3) { @@ -250,22 +252,22 @@ pl_Mdl *plMakeCylinder(float r, float h, uint32_t divr, bool captop, f->Vertices[0] = topverts + 0; f->Vertices[1] = topverts + 2; f->Vertices[2] = topverts + 1; - f->MappingU[0] = (int32_t) topverts[0].xformedx; - f->MappingV[0] = (int32_t) topverts[0].xformedy; - f->MappingU[1] = (int32_t) topverts[1].xformedx; - f->MappingV[1] = (int32_t) topverts[1].xformedy; - f->MappingU[2] = (int32_t) topverts[2].xformedx; - f->MappingV[2] = (int32_t) topverts[2].xformedy; + f->MappingU[0] = texcoords[((f->Vertices[0] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((f->Vertices[0] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((f->Vertices[2] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((f->Vertices[2] - mdl->Vertices) * 2) + 1]; + f->MappingU[2] = texcoords[((f->Vertices[1] - mdl->Vertices) * 2) + 0]; + f->MappingV[2] = texcoords[((f->Vertices[1] - mdl->Vertices) * 2) + 1]; f->Material = m; f++; } else { for (i = 0; i < divr; i ++) { f->Vertices[0] = topverts + (i == divr-1 ? 0 : i + 1); f->Vertices[1] = topverts + i; f->Vertices[2] = topcapvert; - f->MappingU[0] = (int32_t) topverts[(i==divr-1?0:i+1)].xformedx; - f->MappingV[0] = (int32_t) topverts[(i==divr-1?0:i+1)].xformedy; - f->MappingU[1] = (int32_t) topverts[i].xformedx; - f->MappingV[1] = (int32_t) topverts[i].xformedy; + f->MappingU[0] = texcoords[((&topverts[(i==divr-1?0:i+1)] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((&topverts[(i==divr-1?0:i+1)] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((&topverts[i] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((&topverts[i] - mdl->Vertices) * 2) + 1]; f->MappingU[2] = f->MappingV[2] = 32768; f->Material = m; f++; } @@ -276,27 +278,28 @@ pl_Mdl *plMakeCylinder(float r, float h, uint32_t divr, bool captop, f->Vertices[0] = bottomverts + 0; f->Vertices[1] = bottomverts + 1; f->Vertices[2] = bottomverts + 2; - f->MappingU[0] = (int32_t) bottomverts[0].xformedx; - f->MappingV[0] = (int32_t) bottomverts[0].xformedy; - f->MappingU[1] = (int32_t) bottomverts[1].xformedx; - f->MappingV[1] = (int32_t) bottomverts[1].xformedy; - f->MappingU[2] = (int32_t) bottomverts[2].xformedx; - f->MappingV[2] = (int32_t) bottomverts[2].xformedy; + f->MappingU[0] = texcoords[((f->Vertices[0] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((f->Vertices[0] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((f->Vertices[1] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((f->Vertices[1] - mdl->Vertices) * 2) + 1]; + f->MappingU[2] = texcoords[((f->Vertices[2] - mdl->Vertices) * 2) + 0]; + f->MappingV[2] = texcoords[((f->Vertices[2] - mdl->Vertices) * 2) + 1]; f->Material = m; f++; } else { for (i = 0; i < divr; i ++) { f->Vertices[0] = bottomverts + i; f->Vertices[1] = bottomverts + (i == divr-1 ? 0 : i + 1); f->Vertices[2] = bottomcapvert; - f->MappingU[0] = (int32_t) bottomverts[i].xformedx; - f->MappingV[0] = (int32_t) bottomverts[i].xformedy; - f->MappingU[1] = (int32_t) bottomverts[(i==divr-1?0:i+1)].xformedx; - f->MappingV[1] = (int32_t) bottomverts[(i==divr-1?0:i+1)].xformedy; + f->MappingU[0] = texcoords[((&bottomverts[i] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((&bottomverts[i] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((&bottomverts[(i==divr-1?0:i+1)] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((&bottomverts[(i==divr-1?0:i+1)] - mdl->Vertices) * 2) + 1]; f->MappingU[2] = f->MappingV[2] = 32768; f->Material = m; f++; } } } + if (texcoords) plFree(texcoords); plMdlCalcNormals(mdl); return (mdl); } @@ -308,14 +311,16 @@ pl_Mdl *plMakeCone(float r, float h, uint32_t div, pl_Face *f; uint32_t i; double a, da; + int32_t *texcoords = NULL; if (div < 3) div = 3; mdl = plMdlCreate(div + (div == 3 ? 1 : (cap ? 2 : 1)), div + (div == 3 ? 1 : (cap ? div : 0))); if (!mdl) return 0; + texcoords = plMalloc(mdl->NumVertices * sizeof(int32_t) * 2); v = mdl->Vertices; v->x = v->z = 0; v->y = h/2; - v->xformedx = 1<<15; - v->xformedy = 1<<15; + texcoords[((v - mdl->Vertices) * 2) + 0] = 1<<15; + texcoords[((v - mdl->Vertices) * 2) + 1] = 1<<15; v++; a = 0.0; da = (2.0*PL_PI)/div; @@ -323,16 +328,16 @@ pl_Mdl *plMakeCone(float r, float h, uint32_t div, v->y = h/-2.0f; v->x = (float) (r*plCos((double) a)); v->z = (float) (r*plSin((double) a)); - v->xformedx = (float) (32768.0 + (plCos((double) a)*32768.0)); - v->xformedy = (float) (32768.0 + (plSin((double) a)*32768.0)); + texcoords[((v - mdl->Vertices) * 2) + 0] = (int32_t) (32768.0 + (plCos((double) a)*32768.0)); + texcoords[((v - mdl->Vertices) * 2) + 1] = (int32_t) (32768.0 + (plSin((double) a)*32768.0)); a += da; v++; } if (cap && div != 3) { v->y = h / -2.0f; v->x = v->z = 0.0f; - v->xformedx = (float) (1<<15); - v->xformedy = (float) (1<<15); + texcoords[((v - mdl->Vertices) * 2) + 0] = 1<<15; + texcoords[((v - mdl->Vertices) * 2) + 1] = 1<<15; v++; } f = mdl->Faces; @@ -340,12 +345,12 @@ pl_Mdl *plMakeCone(float r, float h, uint32_t div, f->Vertices[0] = mdl->Vertices; f->Vertices[1] = mdl->Vertices + (i == div ? 1 : i + 1); f->Vertices[2] = mdl->Vertices + i; - f->MappingU[0] = (int32_t) mdl->Vertices[0].xformedx; - f->MappingV[0] = (int32_t) mdl->Vertices[0].xformedy; - f->MappingU[1] = (int32_t) mdl->Vertices[(i==div?1:i+1)].xformedx; - f->MappingV[1] = (int32_t) mdl->Vertices[(i==div?1:i+1)].xformedy; - f->MappingU[2] = (int32_t) mdl->Vertices[i].xformedx; - f->MappingV[2] = (int32_t) mdl->Vertices[i].xformedy; + f->MappingU[0] = texcoords[((&mdl->Vertices[0] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((&mdl->Vertices[0] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((&mdl->Vertices[(i==div?1:i+1)] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((&mdl->Vertices[(i==div?1:i+1)] - mdl->Vertices) * 2) + 1]; + f->MappingU[2] = texcoords[((&mdl->Vertices[i] - mdl->Vertices) * 2) + 0]; + f->MappingV[2] = texcoords[((&mdl->Vertices[i] - mdl->Vertices) * 2) + 1]; f->Material = m; f++; } @@ -354,12 +359,12 @@ pl_Mdl *plMakeCone(float r, float h, uint32_t div, f->Vertices[0] = mdl->Vertices + 1; f->Vertices[1] = mdl->Vertices + 2; f->Vertices[2] = mdl->Vertices + 3; - f->MappingU[0] = (int32_t) mdl->Vertices[1].xformedx; - f->MappingV[0] = (int32_t) mdl->Vertices[1].xformedy; - f->MappingU[1] = (int32_t) mdl->Vertices[2].xformedx; - f->MappingV[1] = (int32_t) mdl->Vertices[2].xformedy; - f->MappingU[2] = (int32_t) mdl->Vertices[3].xformedx; - f->MappingV[2] = (int32_t) mdl->Vertices[3].xformedy; + f->MappingU[0] = texcoords[((&mdl->Vertices[1] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((&mdl->Vertices[1] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((&mdl->Vertices[2] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((&mdl->Vertices[2] - mdl->Vertices) * 2) + 1]; + f->MappingU[2] = texcoords[((&mdl->Vertices[3] - mdl->Vertices) * 2) + 0]; + f->MappingV[2] = texcoords[((&mdl->Vertices[3] - mdl->Vertices) * 2) + 1]; f->Material = m; f++; } else { @@ -367,17 +372,18 @@ pl_Mdl *plMakeCone(float r, float h, uint32_t div, f->Vertices[0] = mdl->Vertices + div + 1; f->Vertices[1] = mdl->Vertices + i; f->Vertices[2] = mdl->Vertices + (i==div ? 1 : i+1); - f->MappingU[0] = (int32_t) mdl->Vertices[div+1].xformedx; - f->MappingV[0] = (int32_t) mdl->Vertices[div+1].xformedy; - f->MappingU[1] = (int32_t) mdl->Vertices[i].xformedx; - f->MappingV[1] = (int32_t) mdl->Vertices[i].xformedy; - f->MappingU[2] = (int32_t) mdl->Vertices[i==div?1:i+1].xformedx; - f->MappingV[2] = (int32_t) mdl->Vertices[i==div?1:i+1].xformedy; + f->MappingU[0] = texcoords[((&mdl->Vertices[div+1] - mdl->Vertices) * 2) + 0]; + f->MappingV[0] = texcoords[((&mdl->Vertices[div+1] - mdl->Vertices) * 2) + 1]; + f->MappingU[1] = texcoords[((&mdl->Vertices[i] - mdl->Vertices) * 2) + 0]; + f->MappingV[1] = texcoords[((&mdl->Vertices[i] - mdl->Vertices) * 2) + 1]; + f->MappingU[2] = texcoords[((&mdl->Vertices[i==div?1:i+1] - mdl->Vertices) * 2) + 0]; + f->MappingV[2] = texcoords[((&mdl->Vertices[i==div?1:i+1] - mdl->Vertices) * 2) + 1]; f->Material = m; f++; } } } + if (texcoords) plFree(texcoords); plMdlCalcNormals(mdl); return (mdl); } diff --git a/source/mdl.c b/source/mdl.c index 42da486..57bbcbe 100644 --- a/source/mdl.c +++ b/source/mdl.c @@ -59,9 +59,6 @@ pl_Mdl *plMdlCreate(uint32_t nv, uint32_t nf) { pl_Mdl *mdl; - if (!nv || !nf) - return NULL; - mdl = plResCreate(NULL, sizeof(pl_Mdl)); plMemSet(mdl, 0, sizeof(pl_Mdl)); @@ -69,11 +66,17 @@ pl_Mdl *plMdlCreate(uint32_t nv, uint32_t nf) mdl->NumVertices = nv; mdl->NumFaces = nf; - mdl->Vertices = plResCreate(mdl, sizeof(pl_Vertex) * mdl->NumVertices); - mdl->Faces = plResCreate(mdl, sizeof(pl_Face) * mdl->NumFaces); + if (nv) + { + mdl->Vertices = plResCreate(mdl, sizeof(pl_Vertex) * mdl->NumVertices); + plMemSet(mdl->Vertices, 0, sizeof(pl_Vertex) * mdl->NumVertices); + } - plMemSet(mdl->Vertices, 0, sizeof(pl_Vertex) * mdl->NumVertices); - plMemSet(mdl->Faces, 0, sizeof(pl_Face) * mdl->NumFaces); + if (nf) + { + mdl->Faces = plResCreate(mdl, sizeof(pl_Face) * mdl->NumFaces); + plMemSet(mdl->Faces, 0, sizeof(pl_Face) * mdl->NumFaces); + } return mdl; } diff --git a/source/pf_ptex.c b/source/pf_ptex.c index 6ce7159..22729bd 100644 --- a/source/pf_ptex.c +++ b/source/pf_ptex.c @@ -9,10 +9,10 @@ Copyright (C) 2024-2025, erysdren (it/its) #include #include "putface.h" -void plPF_PTexF(pl_Cam *cam, pl_Face *TriFace) { +void plPF_PTexF(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; - uint8_t *remap = TriFace->Material->_ReMapTable; + uint8_t *remap = TriFace->Face->Material->_ReMapTable; float *zbuf = cam->zBuffer; float MappingU1, MappingU2, MappingU3; float MappingV1, MappingV2, MappingV3; @@ -36,10 +36,10 @@ void plPF_PTexF(pl_Cam *cam, pl_Face *TriFace) { bool masked; uint8_t texel; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; - if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; - else Texture = TriFace->Material->Texture; + if (TriFace->Face->Material->Environment) Texture = TriFace->Face->Material->Environment; + else Texture = TriFace->Face->Material->Texture; if (!Texture) return; masked = Texture->ClearColor >= 0 && Texture->ClearColor <= 255; @@ -48,9 +48,9 @@ void plPF_PTexF(pl_Cam *cam, pl_Face *TriFace) { if (iShade < 0) iShade=0; if (iShade > 255) iShade=255; - if (!TriFace->Material->_AddTable) bc=0; - else bc = TriFace->Material->_AddTable[iShade]; - nm = TriFace->Material->PerspectiveCorrect; + if (!TriFace->Face->Material->_AddTable) bc=0; + else bc = TriFace->Face->Material->_AddTable[iShade]; + nm = TriFace->Face->Material->PerspectiveCorrect; nmb = 0; while (nm) { nmb++; nm >>= 1; } nmb = plMin(6,nmb); nm = 1<Width)-1; vshift = 16 - Texture->Width; - if (TriFace->Material->Environment) { + if (TriFace->Face->Material->Environment) { PUTFACE_SORT_ENV(); } else { PUTFACE_SORT_TEX(); @@ -224,13 +224,13 @@ void plPF_PTexF(pl_Cam *cam, pl_Face *TriFace) { } } -void plPF_PTexG(pl_Cam *cam, pl_Face *TriFace) { +void plPF_PTexG(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; float MappingU1, MappingU2, MappingU3; float MappingV1, MappingV2, MappingV3; pl_Texture *Texture; - bool zb = (cam->zBuffer&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (cam->zBuffer&&TriFace->Face->Material->zBufferable) ? 1 : 0; uint8_t nm, nmb; uint32_t n; @@ -238,7 +238,7 @@ void plPF_PTexG(pl_Cam *cam, pl_Face *TriFace) { uint8_t vshift; uint8_t *texture; uint16_t *addtable; - uint8_t *remap = TriFace->Material->_ReMapTable; + uint8_t *remap = TriFace->Face->Material->_ReMapTable; int32_t iUL, iVL, idUL, idVL, iULnext, iVLnext; float U2,V2,dU2=0,dV2=0,dUL=0,dVL=0,UL,VL; int32_t XL1, Xlen; @@ -260,16 +260,16 @@ void plPF_PTexG(pl_Cam *cam, pl_Face *TriFace) { uint8_t *gmem = cam->frameBuffer; float *zbuf = cam->zBuffer; - if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; - else Texture = TriFace->Material->Texture; + if (TriFace->Face->Material->Environment) Texture = TriFace->Face->Material->Environment; + else Texture = TriFace->Face->Material->Texture; if (!Texture) return; masked = Texture->ClearColor >= 0 && Texture->ClearColor <= 255; texture = Texture->Data; - addtable = TriFace->Material->_AddTable; + addtable = TriFace->Face->Material->_AddTable; if (!addtable) return; - nm = TriFace->Material->PerspectiveCorrect; + nm = TriFace->Face->Material->PerspectiveCorrect; nmb = 0; while (nm) { nmb++; nm >>= 1; } nmb = plMin(6,nmb); nm = 1<Width)-1; vshift = 16 - Texture->Width; - if (TriFace->Material->Environment) { + if (TriFace->Face->Material->Environment) { PUTFACE_SORT_ENV(); } else { PUTFACE_SORT_TEX(); diff --git a/source/pf_solid.c b/source/pf_solid.c index d9b617f..76b6c52 100644 --- a/source/pf_solid.c +++ b/source/pf_solid.c @@ -9,7 +9,7 @@ Copyright (C) 2024-2025, erysdren (it/its) #include #include "putface.h" -void plPF_SolidF(pl_Cam *cam, pl_Face *TriFace) { +void plPF_SolidF(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; @@ -19,16 +19,16 @@ void plPF_SolidF(pl_Cam *cam, pl_Face *TriFace) { float dZL=0, dZ1=0, dZ2=0, Z1, ZL, Z2, Z3; int32_t Y1, Y2, Y0, dY; uint8_t stat; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; uint8_t bc; int32_t shade; PUTFACE_SORT(); - shade=(int32_t) (TriFace->fShade*(TriFace->Material->_ColorsUsed-1)); + shade=(int32_t) (TriFace->fShade*(TriFace->Face->Material->_ColorsUsed-1)); if (shade < 0) shade=0; - if (shade > (int32_t) TriFace->Material->_ColorsUsed-1) shade=TriFace->Material->_ColorsUsed-1; - bc=TriFace->Material->_ReMapTable[shade]; + if (shade > (int32_t) TriFace->Face->Material->_ColorsUsed-1) shade=TriFace->Face->Material->_ColorsUsed-1; + bc=TriFace->Face->Material->_ReMapTable[shade]; X2 = X1 = TriFace->Scrx[i0]; Z1 = TriFace->Scrz[i0]; @@ -130,21 +130,21 @@ void plPF_SolidF(pl_Cam *cam, pl_Face *TriFace) { } } -void plPF_SolidG(pl_Cam *cam, pl_Face *TriFace) { +void plPF_SolidG(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; - uint8_t *remap = TriFace->Material->_ReMapTable; + uint8_t *remap = TriFace->Face->Material->_ReMapTable; float *zbuf = cam->zBuffer; float dZL=0, dZ1=0, dZ2=0, Z1, Z2, ZL, Z3; int32_t dX1=0, dX2=0, X1, X2, XL1, XL2; int32_t C1, C2, dC1=0, dC2=0, dCL=0, CL, C3; int32_t Y1, Y2, Y0, dY; uint8_t stat; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; - float nc = (TriFace->Material->_ColorsUsed-1)*65536.0f; - int32_t maxColor=((TriFace->Material->_ColorsUsed-1)<<16); - int32_t maxColorNonShift=TriFace->Material->_ColorsUsed-1; + float nc = (TriFace->Face->Material->_ColorsUsed-1)*65536.0f; + int32_t maxColor=((TriFace->Face->Material->_ColorsUsed-1)<<16); + int32_t maxColorNonShift=TriFace->Face->Material->_ColorsUsed-1; PUTFACE_SORT(); diff --git a/source/pf_tex.c b/source/pf_tex.c index 3030693..3f846b0 100644 --- a/source/pf_tex.c +++ b/source/pf_tex.c @@ -10,7 +10,7 @@ Copyright (C) 2024-2025, erysdren (it/its) #include "putface.h" -void plPF_TexEnv(pl_Cam *cam, pl_Face *TriFace) { +void plPF_TexEnv(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; uint8_t *remap; @@ -29,7 +29,7 @@ void plPF_TexEnv(pl_Cam *cam, pl_Face *TriFace) { uint16_t *addtable; pl_Texture *Texture, *Environment; uint8_t stat; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; int32_t U1, V1, U2, V2, dU1=0, dU2=0, dV1=0, dV2=0, dUL=0, dVL=0, UL, VL; int32_t eU1, eV1, eU2, eV2, edU1=0, edU2=0, edV1=0, @@ -40,15 +40,15 @@ void plPF_TexEnv(pl_Cam *cam, pl_Face *TriFace) { bool masked; uint8_t texel; - Environment = TriFace->Material->Environment; - Texture = TriFace->Material->Texture; + Environment = TriFace->Face->Material->Environment; + Texture = TriFace->Face->Material->Texture; if (!Texture || !Environment) return; masked = Texture->ClearColor >= 0 && Texture->ClearColor <= 255; texture = Texture->Data; environment = Environment->Data; - addtable = TriFace->Material->_AddTable; - remap = TriFace->Material->_ReMapTable; + addtable = TriFace->Face->Material->_AddTable; + remap = TriFace->Face->Material->_ReMapTable; MappingV_AND = ((1<Height)-1)<Width; MappingU_AND = (1<Width)-1; @@ -59,12 +59,12 @@ void plPF_TexEnv(pl_Cam *cam, pl_Face *TriFace) { PUTFACE_SORT_TEX(); - eMappingU1=(int32_t) (TriFace->eMappingU[i0]*Environment->uScale*TriFace->Material->EnvScaling); - eMappingV1=(int32_t) (TriFace->eMappingV[i0]*Environment->vScale*TriFace->Material->EnvScaling); - eMappingU2=(int32_t) (TriFace->eMappingU[i1]*Environment->uScale*TriFace->Material->EnvScaling); - eMappingV2=(int32_t) (TriFace->eMappingV[i1]*Environment->vScale*TriFace->Material->EnvScaling); - eMappingU3=(int32_t) (TriFace->eMappingU[i2]*Environment->uScale*TriFace->Material->EnvScaling); - eMappingV3=(int32_t) (TriFace->eMappingV[i2]*Environment->vScale*TriFace->Material->EnvScaling); + eMappingU1=(int32_t) (TriFace->eMappingU[i0]*Environment->uScale*TriFace->Face->Material->EnvScaling); + eMappingV1=(int32_t) (TriFace->eMappingV[i0]*Environment->vScale*TriFace->Face->Material->EnvScaling); + eMappingU2=(int32_t) (TriFace->eMappingU[i1]*Environment->uScale*TriFace->Face->Material->EnvScaling); + eMappingV2=(int32_t) (TriFace->eMappingV[i1]*Environment->vScale*TriFace->Face->Material->EnvScaling); + eMappingU3=(int32_t) (TriFace->eMappingU[i2]*Environment->uScale*TriFace->Face->Material->EnvScaling); + eMappingV3=(int32_t) (TriFace->eMappingV[i2]*Environment->vScale*TriFace->Face->Material->EnvScaling); U1 = U2 = MappingU1; V1 = V2 = MappingV1; @@ -224,7 +224,7 @@ void plPF_TexEnv(pl_Cam *cam, pl_Face *TriFace) { } } -void plPF_TexF(pl_Cam *cam, pl_Face *TriFace) { +void plPF_TexF(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; float *zbuf = cam->zBuffer; @@ -243,23 +243,23 @@ void plPF_TexF(pl_Cam *cam, pl_Face *TriFace) { int32_t dUL=0, dVL=0, UL, VL; int32_t X1, X2, dX1=0, dX2=0, XL1, XL2; int32_t Y1, Y2, Y0, dY; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; int32_t shade; bool masked; uint8_t texel; - if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; - else Texture = TriFace->Material->Texture; + if (TriFace->Face->Material->Environment) Texture = TriFace->Face->Material->Environment; + else Texture = TriFace->Face->Material->Texture; if (!Texture) return; masked = Texture->ClearColor >= 0 && Texture->ClearColor <= 255; - remap = TriFace->Material->_ReMapTable; - if (TriFace->Material->_AddTable) + remap = TriFace->Face->Material->_ReMapTable; + if (TriFace->Face->Material->_AddTable) { shade=(int32_t)(TriFace->fShade*255.0f); if (shade < 0) shade=0; if (shade > 255) shade=255; - bc = TriFace->Material->_AddTable[shade]; + bc = TriFace->Face->Material->_AddTable[shade]; } else bc=0; texture = Texture->Data; @@ -267,7 +267,7 @@ void plPF_TexF(pl_Cam *cam, pl_Face *TriFace) { MappingV_AND = ((1<Height)-1)<Width; MappingU_AND = (1<Width)-1; - if (TriFace->Material->Environment) { + if (TriFace->Face->Material->Environment) { PUTFACE_SORT_ENV(); } else { PUTFACE_SORT_TEX(); @@ -403,7 +403,7 @@ void plPF_TexF(pl_Cam *cam, pl_Face *TriFace) { } } -void plPF_TexG(pl_Cam *cam, pl_Face *TriFace) { +void plPF_TexG(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; float *zbuf = cam->zBuffer; @@ -425,21 +425,21 @@ void plPF_TexG(pl_Cam *cam, pl_Face *TriFace) { int32_t Y1, Y2, Y0, dY; uint8_t stat; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; - if (TriFace->Material->Environment) Texture = TriFace->Material->Environment; - else Texture = TriFace->Material->Texture; + if (TriFace->Face->Material->Environment) Texture = TriFace->Face->Material->Environment; + else Texture = TriFace->Face->Material->Texture; if (!Texture) return; masked = Texture->ClearColor >= 0 && Texture->ClearColor <= 255; - remap = TriFace->Material->_ReMapTable; + remap = TriFace->Face->Material->_ReMapTable; texture = Texture->Data; - addtable = TriFace->Material->_AddTable; + addtable = TriFace->Face->Material->_AddTable; vshift = 16 - Texture->Width; MappingV_AND = ((1<Height)-1)<Width; MappingU_AND = (1<Width)-1; - if (TriFace->Material->Environment) { + if (TriFace->Face->Material->Environment) { PUTFACE_SORT_ENV(); } else { PUTFACE_SORT_TEX(); diff --git a/source/pf_trans.c b/source/pf_trans.c index eb4a3fd..6f9ccdc 100644 --- a/source/pf_trans.c +++ b/source/pf_trans.c @@ -9,22 +9,22 @@ Copyright (C) 2024-2025, erysdren (it/its) #include #include "putface.h" -void plPF_TransF(pl_Cam *cam, pl_Face *TriFace) { +void plPF_TransF(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; - uint8_t *remap = TriFace->Material->_ReMapTable; + uint8_t *remap = TriFace->Face->Material->_ReMapTable; float *zbuf = cam->zBuffer; int32_t X1, X2, dX1=0, dX2=0, XL1, XL2; float Z1, ZL, dZ1=0, dZL=0, dZ2=0, Z2; int32_t Y1, Y2, Y0, dY; - uint16_t *lookuptable = TriFace->Material->_AddTable; + uint16_t *lookuptable = TriFace->Face->Material->_AddTable; uint8_t stat; - int32_t bc = (int32_t) TriFace->fShade*TriFace->Material->_tsfact; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + int32_t bc = (int32_t) TriFace->fShade*TriFace->Face->Material->_tsfact; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; PUTFACE_SORT(); - if (bc > (int32_t) TriFace->Material->_tsfact-1) bc=TriFace->Material->_tsfact-1; + if (bc > (int32_t) TriFace->Face->Material->_tsfact-1) bc=TriFace->Face->Material->_tsfact-1; if (bc < 0) bc=0; remap+=bc; @@ -124,22 +124,22 @@ void plPF_TransF(pl_Cam *cam, pl_Face *TriFace) { } } -void plPF_TransG(pl_Cam *cam, pl_Face *TriFace) { +void plPF_TransG(pl_Cam *cam, pl_PrepFace *TriFace) { uint8_t i0, i1, i2; uint8_t *gmem = cam->frameBuffer; - uint8_t *remap = TriFace->Material->_ReMapTable; + uint8_t *remap = TriFace->Face->Material->_ReMapTable; float *zbuf = cam->zBuffer; int32_t X1, X2, dX1=0, dX2=0, XL1, XL2; float Z1, ZL, dZ1=0, dZL=0, dZ2=0, Z2; int32_t dC1=0, dCL=0, CL, C1, C2, dC2=0; int32_t Y1, Y2, Y0, dY; - float nc = (TriFace->Material->_tsfact*65536.0f); - uint16_t *lookuptable = TriFace->Material->_AddTable; - bool zb = (zbuf&&TriFace->Material->zBufferable) ? 1 : 0; + float nc = (TriFace->Face->Material->_tsfact*65536.0f); + uint16_t *lookuptable = TriFace->Face->Material->_AddTable; + bool zb = (zbuf&&TriFace->Face->Material->zBufferable) ? 1 : 0; uint8_t stat; - int32_t maxColor=((TriFace->Material->_tsfact-1)<<16); - int32_t maxColorNonShift=TriFace->Material->_tsfact-1; + int32_t maxColor=((TriFace->Face->Material->_tsfact-1)<<16); + int32_t maxColorNonShift=TriFace->Face->Material->_tsfact-1; PUTFACE_SORT(); diff --git a/source/putface.h b/source/putface.h index f7276bd..f4aef12 100644 --- a/source/putface.h +++ b/source/putface.h @@ -25,31 +25,31 @@ Copyright (C) 2024-2025, erysdren (it/its) #define PUTFACE_SORT_ENV() \ PUTFACE_SORT(); \ MappingU1=TriFace->eMappingU[i0]*Texture->uScale*\ - TriFace->Material->EnvScaling;\ + TriFace->Face->Material->EnvScaling;\ MappingV1=TriFace->eMappingV[i0]*Texture->vScale*\ - TriFace->Material->EnvScaling;\ + TriFace->Face->Material->EnvScaling;\ MappingU2=TriFace->eMappingU[i1]*Texture->uScale*\ - TriFace->Material->EnvScaling;\ + TriFace->Face->Material->EnvScaling;\ MappingV2=TriFace->eMappingV[i1]*Texture->vScale*\ - TriFace->Material->EnvScaling;\ + TriFace->Face->Material->EnvScaling;\ MappingU3=TriFace->eMappingU[i2]*Texture->uScale*\ - TriFace->Material->EnvScaling;\ + TriFace->Face->Material->EnvScaling;\ MappingV3=TriFace->eMappingV[i2]*Texture->vScale*\ - TriFace->Material->EnvScaling; + TriFace->Face->Material->EnvScaling; #define PUTFACE_SORT_TEX() \ PUTFACE_SORT(); \ MappingU1=TriFace->MappingU[i0]*Texture->uScale*\ - TriFace->Material->TexScaling;\ + TriFace->Face->Material->TexScaling;\ MappingV1=TriFace->MappingV[i0]*Texture->vScale*\ - TriFace->Material->TexScaling;\ + TriFace->Face->Material->TexScaling;\ MappingU2=TriFace->MappingU[i1]*Texture->uScale*\ - TriFace->Material->TexScaling;\ + TriFace->Face->Material->TexScaling;\ MappingV2=TriFace->MappingV[i1]*Texture->vScale*\ - TriFace->Material->TexScaling;\ + TriFace->Face->Material->TexScaling;\ MappingU3=TriFace->MappingU[i2]*Texture->uScale*\ - TriFace->Material->TexScaling;\ + TriFace->Face->Material->TexScaling;\ MappingV3=TriFace->MappingV[i2]*Texture->vScale*\ - TriFace->Material->TexScaling; + TriFace->Face->Material->TexScaling; #endif /* !_PUTFACE_H_ */ diff --git a/source/read_3ds.c b/source/read_3ds.c index 38f035c..6585805 100644 --- a/source/read_3ds.c +++ b/source/read_3ds.c @@ -18,6 +18,8 @@ static pl_Obj *bobj; static pl_Obj *lobj; static int16_t currentobj; static pl_Mat *_m; +static int32_t *_texcoords = NULL; +static int32_t _num_texcoords = 0; static float _pl3DSReadFloat(FILE *f); static uint32_t _pl3DSReadDWord(FILE *f); @@ -65,6 +67,9 @@ pl_Obj *plRead3DSObj(const char *fn, pl_Mat *m) { rewind(f); _pl3DSChunkReader(f, p); fclose(f); + if (_texcoords) plFree(_texcoords); + _texcoords = NULL; + _num_texcoords = 0; return bobj; } @@ -130,12 +135,12 @@ static void _pl3DSTriMeshReader(FILE *f, uint32_t p) { face->Vertices[0] = obj->Model->Vertices + (ptrdiff_t) face->Vertices[0]; face->Vertices[1] = obj->Model->Vertices + (ptrdiff_t) face->Vertices[1]; face->Vertices[2] = obj->Model->Vertices + (ptrdiff_t) face->Vertices[2]; - face->MappingU[0] = face->Vertices[0]->xformedx; - face->MappingV[0] = face->Vertices[0]->xformedy; - face->MappingU[1] = face->Vertices[1]->xformedx; - face->MappingV[1] = face->Vertices[1]->xformedy; - face->MappingU[2] = face->Vertices[2]->xformedx; - face->MappingV[2] = face->Vertices[2]->xformedy; + face->MappingU[0] = _texcoords[((face->Vertices[0] - obj->Model->Vertices) * 2) + 0]; + face->MappingV[0] = _texcoords[((face->Vertices[0] - obj->Model->Vertices) * 2) + 1]; + face->MappingU[1] = _texcoords[((face->Vertices[1] - obj->Model->Vertices) * 2) + 0]; + face->MappingV[1] = _texcoords[((face->Vertices[1] - obj->Model->Vertices) * 2) + 1]; + face->MappingU[2] = _texcoords[((face->Vertices[2] - obj->Model->Vertices) * 2) + 0]; + face->MappingV[2] = _texcoords[((face->Vertices[2] - obj->Model->Vertices) * 2) + 1]; face++; } plMdlCalcNormals(obj->Model); @@ -153,7 +158,7 @@ static void _pl3DSVertListReader(FILE *f, uint32_t p) { pl_Vertex *v; nv = _pl3DSReadWord(f); obj->Model->NumVertices = nv; - v = obj->Model->Vertices = (pl_Vertex *) plCalloc(sizeof(pl_Vertex)*nv,1); + v = obj->Model->Vertices = plResCreate(obj->Model, sizeof(pl_Vertex) * nv); while (nv--) { v->x = _pl3DSReadFloat(f); v->y = _pl3DSReadFloat(f); @@ -171,7 +176,7 @@ static void _pl3DSFaceListReader(FILE *f, uint32_t p) { nv = _pl3DSReadWord(f); obj->Model->NumFaces = nv; - face = obj->Model->Faces = (pl_Face *) plCalloc(sizeof(pl_Face)*nv,1); + face = obj->Model->Faces = plResCreate(obj->Model, sizeof(pl_Face) * nv); while (nv--) { c[0] = _pl3DSReadWord(f); c[1] = _pl3DSReadWord(f); @@ -208,8 +213,10 @@ static void MapListReader(FILE *f, uint32_t p) { c[0] = _pl3DSReadFloat(f); c[1] = _pl3DSReadFloat(f); if (feof(f)) return; - v->xformedx = (int32_t) (c[0]*65536.0); - v->xformedy = (int32_t) (c[1]*65536.0); + _texcoords = plRealloc(_texcoords, (_num_texcoords + 2) * sizeof(int32_t)); + _texcoords[((v - obj->Model->Vertices) * 2) + 0] = (int32_t) (c[0]*65536.0); + _texcoords[((v - obj->Model->Vertices) * 2) + 1] = (int32_t) (c[1]*65536.0); + _num_texcoords += 2; v++; } } @@ -243,4 +250,3 @@ static void _pl3DSChunkReader(FILE *f, uint32_t p) { if (ferror(f)) break; } } - diff --git a/source/render.c b/source/render.c index 885d2b2..27852dd 100644 --- a/source/render.c +++ b/source/render.c @@ -8,15 +8,9 @@ Copyright (C) 2024-2025, erysdren (it/its) #include -typedef struct { - float zd; - pl_Face *face; -} _faceInfo; - -typedef struct { - pl_Light *light; - float l[3]; -} _lightInfo; +void plClipSetFrustum(pl_Cam *cam); +void plClipRenderFace(pl_PrepFace *face); +int32_t plClipNeeded(pl_PrepFace *face); #define MACRO_plMatrixApply(m,x,y,z,outx,outy,outz) \ ( outx ) = ( x )*( m )[0] + ( y )*( m )[1] + ( z )*( m )[2] + ( m )[3];\ @@ -40,15 +34,18 @@ typedef struct { uint32_t plRender_TriStats[4]; static uint32_t _numfaces; -static _faceInfo _faces[PL_MAX_TRIANGLES]; +static pl_PrepFace _faces[PL_MAX_TRIANGLES]; + +static uint32_t _numvertices; +static pl_PrepVertex _vertices[PL_MAX_VERTICES]; static float _cMatrix[16]; static uint32_t _numlights; -static _lightInfo _lights[PL_MAX_LIGHTS]; +static pl_PrepLight _lights[PL_MAX_LIGHTS]; static pl_Cam *_cam; static void _RenderObj(pl_Obj *, float *, float *); static void _sift_down(int L, int U, int dir); -static void _hsort(_faceInfo *base, int nel, int dir); +static void _hsort(pl_PrepFace *base, int nel, int dir); void plRenderBegin(pl_Cam *Camera) { float tempMatrix[16]; @@ -56,6 +53,7 @@ void plRenderBegin(pl_Cam *Camera) { _cam = Camera; _numlights = 0; _numfaces = 0; + _numvertices = 0; plMatrixRotate(_cMatrix,2,-Camera->Pan); plMatrixRotate(tempMatrix,1,-Camera->Pitch); plMatrixMultiply(_cMatrix,tempMatrix); @@ -82,185 +80,221 @@ void plRenderLight(pl_Light *light) { _lights[_numlights++].light = light; } -static void _RenderObj(pl_Obj *obj, float *bmatrix, float *bnmatrix) { - uint32_t i, x, facepos; - float nx = 0.0, ny = 0.0, nz = 0.0; - double tmp, tmp2; - float oMatrix[16], nMatrix[16], tempMatrix[16]; - - pl_Vertex *vertex; - pl_Face *face; - pl_Light *light; - pl_Obj *child; - - if (obj->GenMatrix) { - plMatrixRotate(nMatrix,1,obj->Xa); - plMatrixRotate(tempMatrix,2,obj->Ya); - plMatrixMultiply(nMatrix,tempMatrix); - plMatrixRotate(tempMatrix,3,obj->Za); - plMatrixMultiply(nMatrix,tempMatrix); - plMemCpy(oMatrix,nMatrix,sizeof(float)*16); - } else plMemCpy(nMatrix,obj->RotMatrix,sizeof(float)*16); - - if (bnmatrix) plMatrixMultiply(nMatrix,bnmatrix); - - if (obj->GenMatrix) { - plMatrixTranslate(tempMatrix, obj->Xp, obj->Yp, obj->Zp); - plMatrixMultiply(oMatrix,tempMatrix); - } else plMemCpy(oMatrix,obj->Matrix,sizeof(float)*16); - if (bmatrix) plMatrixMultiply(oMatrix,bmatrix); - - // erysdren - child = obj->Children; - while (child) - { - _RenderObj(child,oMatrix,nMatrix); - child = child->NextSibling; - } +static void _RenderObj(pl_Obj *obj, float *bmatrix, float *bnmatrix) +{ + uint32_t i, x, facepos; + float nx = 0.0, ny = 0.0, nz = 0.0; + double tmp, tmp2; + float oMatrix[16], nMatrix[16], tempMatrix[16]; - if (!obj->Model) return; + pl_PrepVertex *vertex; + pl_PrepFace *face; + pl_Light *light; + pl_Obj *child; - if (!obj->Model->NumFaces || !obj->Model->NumVertices) return; + if (obj->GenMatrix) { + plMatrixRotate(nMatrix,1,obj->Xa); + plMatrixRotate(tempMatrix,2,obj->Ya); + plMatrixMultiply(nMatrix,tempMatrix); + plMatrixRotate(tempMatrix,3,obj->Za); + plMatrixMultiply(nMatrix,tempMatrix); + plMemCpy(oMatrix,nMatrix,sizeof(float)*16); + } else plMemCpy(nMatrix,obj->RotMatrix,sizeof(float)*16); - plMatrixTranslate(tempMatrix, -_cam->X, -_cam->Y, -_cam->Z); - plMatrixMultiply(oMatrix,tempMatrix); - plMatrixMultiply(oMatrix,_cMatrix); - plMatrixMultiply(nMatrix,_cMatrix); - - x = obj->Model->NumVertices; - vertex = obj->Model->Vertices; + if (bnmatrix) plMatrixMultiply(nMatrix,bnmatrix); - do { - MACRO_plMatrixApply(oMatrix,vertex->x,vertex->y,vertex->z, - vertex->xformedx, vertex->xformedy, vertex->xformedz); - MACRO_plMatrixApply(nMatrix,vertex->nx,vertex->ny,vertex->nz, - vertex->xformednx,vertex->xformedny,vertex->xformednz); - vertex++; - } while (--x); + if (obj->GenMatrix) { + plMatrixTranslate(tempMatrix, obj->Xp, obj->Yp, obj->Zp); + plMatrixMultiply(oMatrix,tempMatrix); + } else plMemCpy(oMatrix,obj->Matrix,sizeof(float)*16); - face = obj->Model->Faces; - facepos = _numfaces; + if (bmatrix) plMatrixMultiply(oMatrix,bmatrix); - if (_numfaces + obj->Model->NumFaces >= PL_MAX_TRIANGLES) // exceeded maximum face coutn - { - return; - } + // erysdren + child = obj->Children; + while (child) + { + _RenderObj(child,oMatrix,nMatrix); + child = child->NextSibling; + } - plRender_TriStats[0] += obj->Model->NumFaces; - _numfaces += obj->Model->NumFaces; - x = obj->Model->NumFaces; + // invalid model + if (!obj->Model) + return; + // invalid model data + if (!obj->Model->NumFaces || !obj->Model->NumVertices) + return; + // exceeded maximum vert count + if (_numvertices + obj->Model->NumVertices >= PL_MAX_VERTICES) + return; + // exceeded maximum face count + if (_numfaces + obj->Model->NumFaces >= PL_MAX_TRIANGLES) + return; - do { - if (obj->BackfaceCull || face->Material->_st & PL_SHADE_FLAT) - { - MACRO_plMatrixApply(nMatrix,face->nx,face->ny,face->nz,nx,ny,nz); - } - if (!obj->BackfaceCull || (MACRO_plDotProduct(nx,ny,nz, - face->Vertices[0]->xformedx, face->Vertices[0]->xformedy, - face->Vertices[0]->xformedz) < 0.0000001)) { - if (plClipNeeded(face)) { - if (face->Material->_st & (PL_SHADE_FLAT|PL_SHADE_FLAT_DISTANCE)) { - tmp = face->sLighting; - if (face->Material->_st & PL_SHADE_FLAT) { - for (i = 0; i < _numlights; i ++) { - tmp2 = 0.0; - light = _lights[i].light; - if (light->Type & PL_LIGHT_POINT_ANGLE) { - double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; - double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; - double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; - MACRO_plNormalizeVector(nx2,ny2,nz2); - tmp2 = MACRO_plDotProduct(nx,ny,nz,nx2,ny2,nz2)*light->Intensity; - } - if (light->Type & PL_LIGHT_POINT_DISTANCE) { - double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; - double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; - double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; - if (light->Type & PL_LIGHT_POINT_ANGLE) { - nx2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/ - light->HalfDistSquared)); - tmp2 *= plMax(0,plMin(1.0,nx2))*light->Intensity; - } else { - tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/ - light->HalfDistSquared)); - tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; - } - } - if (light->Type == PL_LIGHT_VECTOR) - tmp2 = MACRO_plDotProduct(nx,ny,nz,_lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) - * light->Intensity; - if (tmp2 > 0.0) tmp += tmp2; - else if (obj->BackfaceIllumination) tmp -= tmp2; - } /* End of light loop */ - } /* End of flat shading if */ - if (face->Material->_st & PL_SHADE_FLAT_DISTANCE) - tmp += 1.0-(face->Vertices[0]->xformedz+face->Vertices[1]->xformedz+ - face->Vertices[2]->xformedz) / - (face->Material->FadeDist*3.0); - face->fShade = (float) tmp; - } else face->fShade = 0.0; /* End of flatmask lighting if */ - if (face->Material->_ft & PL_FILL_ENVIRONMENT) { - face->eMappingU[0] = 32768 + (int32_t) (face->Vertices[0]->xformednx*32768.0); - face->eMappingV[0] = 32768 - (int32_t) (face->Vertices[0]->xformedny*32768.0); - face->eMappingU[1] = 32768 + (int32_t) (face->Vertices[1]->xformednx*32768.0); - face->eMappingV[1] = 32768 - (int32_t) (face->Vertices[1]->xformedny*32768.0); - face->eMappingU[2] = 32768 + (int32_t) (face->Vertices[2]->xformednx*32768.0); - face->eMappingV[2] = 32768 - (int32_t) (face->Vertices[2]->xformedny*32768.0); - } - if (face->Material->_st &(PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE)) { - uint8_t a; - for (a = 0; a < 3; a ++) { - tmp = face->vsLighting[a]; - if (face->Material->_st & PL_SHADE_GOURAUD) { - for (i = 0; i < _numlights ; i++) { - tmp2 = 0.0; - light = _lights[i].light; - if (light->Type & PL_LIGHT_POINT_ANGLE) { - nx = _lights[i].l[0] - face->Vertices[a]->xformedx; - ny = _lights[i].l[1] - face->Vertices[a]->xformedy; - nz = _lights[i].l[2] - face->Vertices[a]->xformedz; - MACRO_plNormalizeVector(nx,ny,nz); - tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx, - face->Vertices[a]->xformedny, - face->Vertices[a]->xformednz, - nx,ny,nz) * light->Intensity; - } - if (light->Type & PL_LIGHT_POINT_DISTANCE) { - double nx2 = _lights[i].l[0] - face->Vertices[a]->xformedx; - double ny2 = _lights[i].l[1] - face->Vertices[a]->xformedy; - double nz2 = _lights[i].l[2] - face->Vertices[a]->xformedz; - if (light->Type & PL_LIGHT_POINT_ANGLE) { - double t= (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); - tmp2 *= plMax(0,plMin(1.0,t))*light->Intensity; - } else { - tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); - tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; - } - } - if (light->Type == PL_LIGHT_VECTOR) - tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx, - face->Vertices[a]->xformedny, - face->Vertices[a]->xformednz, - _lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) - * light->Intensity; - if (tmp2 > 0.0) tmp += tmp2; - else if (obj->BackfaceIllumination) tmp -= tmp2; - } /* End of light loop */ - } /* End of gouraud shading if */ - if (face->Material->_st & PL_SHADE_GOURAUD_DISTANCE) - tmp += 1.0-face->Vertices[a]->xformedz/face->Material->FadeDist; - face->Shades[a] = (float) tmp; - } /* End of vertex loop for */ - } /* End of gouraud shading mask if */ - _faces[facepos].zd = face->Vertices[0]->xformedz+ - face->Vertices[1]->xformedz+face->Vertices[2]->xformedz; - _faces[facepos++].face = face; - plRender_TriStats[1] ++; - } /* Is it in our area Check */ - } /* Backface Check */ - _numfaces = facepos; - face++; - } while (--x); /* Face loop */ + plMatrixTranslate(tempMatrix, -_cam->X, -_cam->Y, -_cam->Z); + plMatrixMultiply(oMatrix,tempMatrix); + plMatrixMultiply(oMatrix,_cMatrix); + plMatrixMultiply(nMatrix,_cMatrix); + + // setup vertices + for (x = 0; x < obj->Model->NumVertices; x++) + { + vertex = _vertices + _numvertices + x; + + vertex->Vertex = obj->Model->Vertices + x; + + MACRO_plMatrixApply( + oMatrix, + vertex->Vertex->x, vertex->Vertex->y, vertex->Vertex->z, + vertex->xformedx, vertex->xformedy, vertex->xformedz + ); + + MACRO_plMatrixApply( + nMatrix, + vertex->Vertex->nx, vertex->Vertex->ny, vertex->Vertex->nz, + vertex->xformednx, vertex->xformedny, vertex->xformednz + ); + } + + plRender_TriStats[0] += obj->Model->NumFaces; + + for (x = 0, facepos = _numfaces; x < obj->Model->NumFaces; x++) + { + face = _faces + facepos; + + face->Face = obj->Model->Faces + x; + + for (i = 0; i < 3; i++) + { + face->Vertices[i] = _vertices + _numvertices + (face->Face->Vertices[i] - obj->Model->Vertices); + + face->MappingU[i] = face->Face->MappingU[i]; + face->MappingV[i] = face->Face->MappingV[i]; + face->eMappingU[i] = face->Face->eMappingU[i]; + face->eMappingV[i] = face->Face->eMappingV[i]; + } + + if (obj->BackfaceCull || face->Face->Material->_st & PL_SHADE_FLAT) + { + MACRO_plMatrixApply(nMatrix, face->Face->nx, face->Face->ny, face->Face->nz, nx, ny, nz); + } + if (!obj->BackfaceCull || (MACRO_plDotProduct(nx,ny,nz,face->Vertices[0]->xformedx, face->Vertices[0]->xformedy,face->Vertices[0]->xformedz) < 0.0000001)) + { + /* Is it in our area Check */ + if (!plClipNeeded(face)) + continue; + + if (face->Face->Material->_st & (PL_SHADE_FLAT|PL_SHADE_FLAT_DISTANCE)) + { + tmp = face->Face->sLighting; + if (face->Face->Material->_st & PL_SHADE_FLAT) + { + for (i = 0; i < _numlights; i ++) + { + tmp2 = 0.0; + light = _lights[i].light; + if (light->Type & PL_LIGHT_POINT_ANGLE) + { + double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; + double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; + double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; + MACRO_plNormalizeVector(nx2,ny2,nz2); + tmp2 = MACRO_plDotProduct(nx,ny,nz,nx2,ny2,nz2)*light->Intensity; + } + if (light->Type & PL_LIGHT_POINT_DISTANCE) + { + double nx2 = _lights[i].l[0] - face->Vertices[0]->xformedx; + double ny2 = _lights[i].l[1] - face->Vertices[0]->xformedy; + double nz2 = _lights[i].l[2] - face->Vertices[0]->xformedz; + if (light->Type & PL_LIGHT_POINT_ANGLE) + { + nx2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); + tmp2 *= plMax(0,plMin(1.0,nx2))*light->Intensity; + } + else + { + tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); + tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; + } + } + if (light->Type == PL_LIGHT_VECTOR) + tmp2 = MACRO_plDotProduct(nx,ny,nz,_lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) * light->Intensity; + if (tmp2 > 0.0) + tmp += tmp2; + else if (obj->BackfaceIllumination) + tmp -= tmp2; + } /* End of light loop */ + } /* End of flat shading if */ + if (face->Face->Material->_st & PL_SHADE_FLAT_DISTANCE) + tmp += 1.0-(face->Vertices[0]->xformedz+face->Vertices[1]->xformedz+face->Vertices[2]->xformedz) / (face->Face->Material->FadeDist*3.0); + face->fShade = (float) tmp; + } + else + { + face->fShade = 0.0; + } /* End of flatmask lighting if */ + if (face->Face->Material->_ft & PL_FILL_ENVIRONMENT) + { + face->eMappingU[0] = 32768 + (int32_t) (face->Vertices[0]->xformednx*32768.0); + face->eMappingV[0] = 32768 - (int32_t) (face->Vertices[0]->xformedny*32768.0); + face->eMappingU[1] = 32768 + (int32_t) (face->Vertices[1]->xformednx*32768.0); + face->eMappingV[1] = 32768 - (int32_t) (face->Vertices[1]->xformedny*32768.0); + face->eMappingU[2] = 32768 + (int32_t) (face->Vertices[2]->xformednx*32768.0); + face->eMappingV[2] = 32768 - (int32_t) (face->Vertices[2]->xformedny*32768.0); + } + if (face->Face->Material->_st &(PL_SHADE_GOURAUD|PL_SHADE_GOURAUD_DISTANCE)) + { + uint8_t a; + for (a = 0; a < 3; a ++) + { + tmp = face->Face->vsLighting[a]; + if (face->Face->Material->_st & PL_SHADE_GOURAUD) + { + for (i = 0; i < _numlights ; i++) + { + tmp2 = 0.0; + light = _lights[i].light; + if (light->Type & PL_LIGHT_POINT_ANGLE) + { + nx = _lights[i].l[0] - face->Vertices[a]->xformedx; + ny = _lights[i].l[1] - face->Vertices[a]->xformedy; + nz = _lights[i].l[2] - face->Vertices[a]->xformedz; + MACRO_plNormalizeVector(nx,ny,nz); + tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx,face->Vertices[a]->xformedny,face->Vertices[a]->xformednz,nx,ny,nz) * light->Intensity; + } + if (light->Type & PL_LIGHT_POINT_DISTANCE) { + double nx2 = _lights[i].l[0] - face->Vertices[a]->xformedx; + double ny2 = _lights[i].l[1] - face->Vertices[a]->xformedy; + double nz2 = _lights[i].l[2] - face->Vertices[a]->xformedz; + if (light->Type & PL_LIGHT_POINT_ANGLE) { + double t= (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); + tmp2 *= plMax(0,plMin(1.0,t))*light->Intensity; + } else { + tmp2 = (1.0 - 0.5*((nx2*nx2+ny2*ny2+nz2*nz2)/light->HalfDistSquared)); + tmp2 = plMax(0,plMin(1.0,tmp2))*light->Intensity; + } + } + if (light->Type == PL_LIGHT_VECTOR) + tmp2 = MACRO_plDotProduct(face->Vertices[a]->xformednx,face->Vertices[a]->xformedny,face->Vertices[a]->xformednz,_lights[i].l[0],_lights[i].l[1],_lights[i].l[2]) * light->Intensity; + if (tmp2 > 0.0) + tmp += tmp2; + else if (obj->BackfaceIllumination) + tmp -= tmp2; + } /* End of light loop */ + } /* End of gouraud shading if */ + if (face->Face->Material->_st & PL_SHADE_GOURAUD_DISTANCE) + tmp += 1.0-face->Vertices[a]->xformedz/face->Face->Material->FadeDist; + face->Shades[a] = (float) tmp; + } /* End of vertex loop for */ + } /* End of gouraud shading mask if */ + face->zd = face->Vertices[0]->xformedz+face->Vertices[1]->xformedz+face->Vertices[2]->xformedz; + facepos++; + plRender_TriStats[1] ++; + } /* Backface Check */ + _numfaces = facepos; + } + + _numvertices += obj->Model->NumVertices; } void plRenderObj(pl_Obj *obj) { @@ -268,24 +302,25 @@ void plRenderObj(pl_Obj *obj) { } void plRenderEnd(void) { - _faceInfo *f; + pl_PrepFace *f; if (_cam->Sort > 0) _hsort(_faces,_numfaces,0); else if (_cam->Sort < 0) _hsort(_faces,_numfaces,1); f = _faces; while (_numfaces--) { - if (f->face->Material && f->face->Material->_PutFace) + if ( f->Face->Material && f->Face->Material->_PutFace) { - plClipRenderFace(f->face); + plClipRenderFace(f); } f++; } - _numfaces=0; + _numfaces = 0; + _numvertices = 0; _numlights = 0; } -static _faceInfo *Base, tmp; +static pl_PrepFace *Base, tmp; -static void _hsort(_faceInfo *base, int nel, int dir) { +static void _hsort(pl_PrepFace *base, int nel, int dir) { static int i; Base=base-1; for (i=nel/2; i>0; i--) _sift_down(i,nel,dir);