Compare commits
2 Commits
Pgta/Duck-
...
skmp/backf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
284f24c48c | ||
|
|
e4b296c4cf |
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@@ -24,6 +24,30 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dca3-sim (linux)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/dreamcast/dca3-sim.elf",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/dreamcast",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dca3-sim (mac)",
|
||||
"type": "cppdbg",
|
||||
|
||||
391
vendor/librw/src/dc/rwdc.cpp
vendored
391
vendor/librw/src/dc/rwdc.cpp
vendored
@@ -4,6 +4,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
|
||||
#if !defined(DC_TEXCONV) && !defined(MACOS64)
|
||||
#include <malloc.h>
|
||||
@@ -595,6 +600,8 @@ struct atomic_context_t {
|
||||
|
||||
matrix_t worldView, mtx;
|
||||
UniformObject uniform;
|
||||
V3d cameraDir;
|
||||
float cosPhi;
|
||||
};
|
||||
/* END Ligting Structs and Defines */
|
||||
|
||||
@@ -1754,24 +1761,23 @@ void addInterpolatedVertex(const pvr_vertex16_t& v1, const pvr_vertex16_t& v2, u
|
||||
}
|
||||
|
||||
struct MeshInfo {
|
||||
int16_t meshletCount;
|
||||
int16_t meshletOffset;
|
||||
uint32_t meshletCount;
|
||||
uint32_t meshletOffset;
|
||||
};
|
||||
static_assert(sizeof(MeshInfo) == 4);
|
||||
static_assert(sizeof(MeshInfo) == 8);
|
||||
|
||||
struct MeshletInfo {
|
||||
RwSphere boundingSphere;
|
||||
uint16_t flags;
|
||||
int8_t pad;
|
||||
uint8_t flags;
|
||||
uint8_t clusterCount;
|
||||
int8_t vertexSize;
|
||||
uint16_t vertexCount;
|
||||
uint16_t indexCount;
|
||||
uint8_t vertexCount;
|
||||
uint32_t vertexOffset;
|
||||
uint32_t indexOffset;
|
||||
uint32_t skinIndexOffset;
|
||||
uint32_t skinWeightOffset;
|
||||
};
|
||||
static_assert(sizeof(MeshletInfo) == 40); // or 32 if !skin
|
||||
static_assert(sizeof(MeshletInfo) == 36); // or 28 if !skin
|
||||
|
||||
|
||||
inline __attribute__((always_inline)) void setLights(Atomic *atomic, WorldLights *lightData, UniformObject &uniformObject)
|
||||
@@ -3229,6 +3235,41 @@ size_t vertexBufferFree() {
|
||||
}
|
||||
|
||||
|
||||
float calculateMaxAngularOffset(
|
||||
const V3d& cameraPos, // Camera position
|
||||
const V3d& cameraLookAt, // Camera look-at point (not direction)
|
||||
const V3d& sphereCenter, // Sphere center
|
||||
float sphereRadius) // Sphere radius
|
||||
{
|
||||
// Compute the look-at direction vector (normalized)
|
||||
V3d frustumAxis = cameraLookAt;
|
||||
|
||||
// Vector from camera to sphere center
|
||||
V3d V = sub(sphereCenter, cameraPos);
|
||||
|
||||
if (length(V) < sphereRadius) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Distance along the camera look-at direction
|
||||
float d_parallel = dot(V, frustumAxis);
|
||||
|
||||
// Perpendicular vector (V_perp = V - d_parallel * frustumAxis)
|
||||
V3d V_perp = {
|
||||
V.x - d_parallel * frustumAxis.x,
|
||||
V.y - d_parallel * frustumAxis.y,
|
||||
V.z - d_parallel * frustumAxis.z
|
||||
};
|
||||
float d_perpendicular = length(V_perp);
|
||||
|
||||
// Total perpendicular distance including sphere radius
|
||||
float d_total = d_perpendicular + sphereRadius;
|
||||
|
||||
// Maximum angular offset
|
||||
float theta_max = std::atan2(d_total, d_parallel);
|
||||
return theta_max; // Result in radians
|
||||
}
|
||||
|
||||
void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
rw::Camera *cam = engine->currentCamera;
|
||||
// Frustum Culling
|
||||
@@ -3286,6 +3327,28 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
mat_apply((matrix_t*)&atomicContexts.back().worldView);
|
||||
mat_store((matrix_t*)&atomicContexts.back().mtx);
|
||||
|
||||
// TODO: Don't invert twice for the same atomic
|
||||
Matrix magic;
|
||||
Matrix::invert(&magic, atomic->getFrame()->getLTM());
|
||||
|
||||
V3d camera_dir;
|
||||
V3d::transformVectors(&camera_dir, &cam->getFrame()->getLTM()->at, 1, &magic);
|
||||
camera_dir = normalize(camera_dir);
|
||||
// required because of camera up being negative
|
||||
camera_dir.x*=-1;
|
||||
camera_dir.y*=-1;
|
||||
camera_dir.z*=-1;
|
||||
|
||||
atomicContexts.back().cameraDir = camera_dir;
|
||||
|
||||
float angle = calculateMaxAngularOffset(cam->getFrame()->getLTM()->pos, cam->getFrame()->getLTM()->at, atomic->getWorldBoundingSphere()->center, atomic->getWorldBoundingSphere()->radius);
|
||||
|
||||
angle = fabs(angle);
|
||||
if (angle > 70/2 * M_PI / 180) {
|
||||
angle = 70/2 * M_PI / 180;
|
||||
}
|
||||
atomicContexts.back().cosPhi = cosf(90 * M_PI / 180 + 5.1 * M_PI / 180 + angle);
|
||||
|
||||
int16_t contextId = atomicContexts.size() - 1;
|
||||
|
||||
assert(numMeshes <= 32767);
|
||||
@@ -3615,9 +3678,37 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
auto indexData = (int8_t*)&dcModel->data[meshlet->indexOffset];
|
||||
|
||||
if (!clippingRequired) {
|
||||
submitMeshletSelector[textured](OCR_SPACE, indexData, meshlet->indexCount);
|
||||
unsigned numClusters = meshlet->clusterCount;
|
||||
auto currentIndexData = indexData;
|
||||
do {
|
||||
V3d coneNormal = { currentIndexData[0] / 127.f, currentIndexData[1] / 127.f, currentIndexData[2] / 127.f };
|
||||
float costheta = dot(acp->cameraDir, coneNormal);
|
||||
unsigned indexCount = (uint8_t&)currentIndexData[3];
|
||||
|
||||
currentIndexData += 4;
|
||||
if (costheta >= acp->cosPhi) {
|
||||
submitMeshletSelector[textured](OCR_SPACE, currentIndexData, indexCount);
|
||||
} else {
|
||||
// printf("CONE CULL, %f %f, %f %f %f\n", costheta, acp->cosPhi, meshlet->coneNormal.x, meshlet->coneNormal.y, meshlet->coneNormal.z);
|
||||
}
|
||||
currentIndexData += indexCount;
|
||||
} while(--numClusters != 0);
|
||||
} else {
|
||||
clipAndsubmitMeshletSelector[textured](OCR_SPACE, indexData, meshlet->indexCount);
|
||||
unsigned numClusters = meshlet->clusterCount;
|
||||
auto currentIndexData = indexData;
|
||||
do {
|
||||
V3d coneNormal = { currentIndexData[0] / 127.f, currentIndexData[1] / 127.f, currentIndexData[2] / 127.f };
|
||||
float costheta = dot(acp->cameraDir, coneNormal);
|
||||
unsigned indexCount = (uint8_t&)currentIndexData[3];
|
||||
|
||||
currentIndexData += 4;
|
||||
if (costheta >= acp->cosPhi) {
|
||||
clipAndsubmitMeshletSelector[textured](OCR_SPACE, currentIndexData, indexCount);
|
||||
} else {
|
||||
// printf("CONE CULL, %f %f, %f %f %f\n", costheta, acp->cosPhi, meshlet->coneNormal.x, meshlet->coneNormal.y, meshlet->coneNormal.z);
|
||||
}
|
||||
currentIndexData += indexCount;
|
||||
} while(--numClusters != 0);
|
||||
}
|
||||
|
||||
if (meshContext->matfxContextOffset != SIZE_MAX) {
|
||||
@@ -3641,9 +3732,37 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
tnlMeshletEnvMap(OCR_SPACE, &dcModel->data[meshlet->vertexOffset] + normalOffset, meshlet->vertexCount, meshlet->vertexSize, &matfxContext->mtx, matfxContext->coefficient);
|
||||
|
||||
if (!clippingRequired) {
|
||||
submitMeshletSelector[true](OCR_SPACE, indexData, meshlet->indexCount);
|
||||
unsigned numClusters = meshlet->clusterCount;
|
||||
auto currentIndexData = indexData;
|
||||
do {
|
||||
V3d coneNormal = { currentIndexData[0] / 127.f, currentIndexData[1] / 127.f, currentIndexData[2] / 127.f };
|
||||
float costheta = dot(acp->cameraDir, coneNormal);
|
||||
unsigned indexCount = (uint8_t&)currentIndexData[3];
|
||||
|
||||
currentIndexData += 4;
|
||||
if (costheta >= acp->cosPhi) {
|
||||
submitMeshletSelector[true](OCR_SPACE, currentIndexData, indexCount);
|
||||
} else {
|
||||
// printf("CONE CULL, %f %f, %f %f %f\n", costheta, acp->cosPhi, meshlet->coneNormal.x, meshlet->coneNormal.y, meshlet->coneNormal.z);
|
||||
}
|
||||
currentIndexData += indexCount;
|
||||
} while(--numClusters != 0);
|
||||
} else {
|
||||
clipAndsubmitMeshletSelector[true](OCR_SPACE, indexData, meshlet->indexCount);
|
||||
unsigned numClusters = meshlet->clusterCount;
|
||||
auto currentIndexData = indexData;
|
||||
do {
|
||||
V3d coneNormal = { currentIndexData[0] / 127.f, currentIndexData[1] / 127.f, currentIndexData[2] / 127.f };
|
||||
float costheta = dot(acp->cameraDir, coneNormal);
|
||||
unsigned indexCount = (uint8_t&)currentIndexData[3];
|
||||
|
||||
currentIndexData += 4;
|
||||
if (costheta >= acp->cosPhi) {
|
||||
clipAndsubmitMeshletSelector[true](OCR_SPACE, currentIndexData, indexCount);
|
||||
} else {
|
||||
// printf("CONE CULL, %f %f, %f %f %f\n", costheta, acp->cosPhi, meshlet->coneNormal.x, meshlet->coneNormal.y, meshlet->coneNormal.z);
|
||||
}
|
||||
currentIndexData += indexCount;
|
||||
} while(--numClusters != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4782,17 +4901,84 @@ centerTexCoords(Geometry *g)
|
||||
rwFree(groupIDs);
|
||||
}
|
||||
|
||||
bool isDegenerate(const V3d& v1, const V3d& v2, const V3d& v3) {
|
||||
// Cluster structure
|
||||
struct ConeCluster {
|
||||
V3d normal; // Average normal of the cluster
|
||||
std::vector<uint32_t> faces; // Indices of triangles in this cluster
|
||||
};
|
||||
|
||||
V3d calculateNormal(const V3d& v1, const V3d& v2, const V3d& v3) {
|
||||
V3d u = {v2.x - v1.x, v2.y - v1.y, v2.z - v1.z};
|
||||
V3d v = {v3.x - v1.x, v3.y - v1.y, v3.z - v1.z};
|
||||
V3d crs = cross(u, v);
|
||||
if (length(crs) < 0.0000001f) {
|
||||
return true;
|
||||
if (length(crs) < 0.00001f) {
|
||||
return {0, 0, 0};
|
||||
} else {
|
||||
return false;
|
||||
return normalize(crs);
|
||||
}
|
||||
}
|
||||
|
||||
// Process mesh with cone clustering logic
|
||||
std::vector<ConeCluster> processMeshWithClustering(uint16_t* indices, uint32_t numIndices, const V3d* vertices, float cosThreshold) {
|
||||
|
||||
std::vector<V3d> triangleNormals(numIndices / 3); // Store triangle normals
|
||||
std::vector<bool> processed(numIndices / 3, false); // Track processed triangles
|
||||
|
||||
// Compute normals for each triangle
|
||||
for (uint32_t i = 0; i < numIndices; i += 3) {
|
||||
uint16_t idx1 = indices[i];
|
||||
uint16_t idx2 = indices[i + 1];
|
||||
uint16_t idx3 = indices[i + 2];
|
||||
|
||||
// Calculate and store the triangle normal
|
||||
triangleNormals[i / 3] = calculateNormal(vertices[idx1], vertices[idx2], vertices[idx3]);
|
||||
}
|
||||
|
||||
// Perform clustering
|
||||
std::vector<ConeCluster> clusters;
|
||||
for (size_t i = 0; i < triangleNormals.size(); ++i) {
|
||||
if (processed[i]) continue;
|
||||
|
||||
if (length(triangleNormals[i]) < 0.000001f)
|
||||
continue;
|
||||
// Create a new cluster
|
||||
ConeCluster cluster;
|
||||
cluster.normal = triangleNormals[i];
|
||||
cluster.faces.push_back(i);
|
||||
processed[i] = true;
|
||||
|
||||
// Find and add similar triangles to this cluster
|
||||
for (size_t j = 0; j < triangleNormals.size(); ++j) {
|
||||
if (processed[j]) continue;
|
||||
|
||||
float similarity = dot(cluster.normal, triangleNormals[j]);
|
||||
if (similarity >= cosThreshold) {
|
||||
cluster.faces.push_back(j);
|
||||
processed[j] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the cluster normal (optional)
|
||||
cluster.normal = normalize(cluster.normal);
|
||||
|
||||
// Store the cluster
|
||||
clusters.push_back(cluster);
|
||||
}
|
||||
|
||||
// // Process each cluster
|
||||
// for (size_t c = 0; c < clusters.size(); ++c) {
|
||||
// std::cout << "Cluster " << c << ":\n";
|
||||
// std::cout << " Average Normal: (" << clusters[c].normal.x << ", " << clusters[c].normal.y << ", " << clusters[c].normal.z << ")\n";
|
||||
// std::cout << " Triangles: ";
|
||||
// for (auto face : clusters[c].faces) {
|
||||
// std::cout << face << " ";
|
||||
// }
|
||||
// std::cout << "\n";
|
||||
// }
|
||||
|
||||
return clusters;
|
||||
}
|
||||
|
||||
bool isDegenerateByIndex(uint16_t idx1, uint16_t idx2, uint16_t idx3) {
|
||||
return idx1 == idx2 || idx1 == idx3 || idx2 == idx3;
|
||||
}
|
||||
@@ -4963,10 +5149,16 @@ RwSphere calculateBoundingSphere(V3d* vertexData, size_t count) {
|
||||
|
||||
return sphere;
|
||||
}
|
||||
|
||||
struct ConeClusterStrip {
|
||||
triangle_stripper::primitive_group* strip;
|
||||
ConeCluster* cluster;
|
||||
};
|
||||
|
||||
struct meshlet {
|
||||
std::set<uint16_t> vertices;
|
||||
std::map<uint16_t, uint8_t> vertexToLocalIndex;
|
||||
std::vector<triangle_stripper::primitive_group*> strips;
|
||||
std::vector<ConeClusterStrip*> strips;
|
||||
size_t vertexDataOffset;
|
||||
size_t indexDataOffset;
|
||||
size_t skinIndexDataOffset;
|
||||
@@ -5024,7 +5216,8 @@ void processGeom(Geometry *geo) {
|
||||
|
||||
int32 n = geo->meshHeader->numMeshes;
|
||||
auto meshes = geo->meshHeader->getMeshes();
|
||||
std::vector<primitive_vector> pvecs(n);
|
||||
std::vector<std::vector<primitive_vector>> pvecs(n);
|
||||
std::vector<std::vector<ConeCluster>> pclus(n);
|
||||
std::vector<std::vector<meshlet>> meshMeshlets(n);
|
||||
|
||||
size_t totalIndices = 0, strips = 0, totalTrilist = 0;
|
||||
@@ -5050,6 +5243,10 @@ void processGeom(Geometry *geo) {
|
||||
skinIndices = (uint32_t*)skin->indices;
|
||||
}
|
||||
|
||||
float angularThreshold = 5.0f * M_PI / 180.0f;
|
||||
float cosThreshold = std::cos(angularThreshold);
|
||||
|
||||
|
||||
|
||||
std::vector<size_t> canonicalIdx(geo->numVertices, SIZE_MAX);
|
||||
for (size_t i = 0; i < geo->numVertices; i++) {
|
||||
@@ -5097,6 +5294,7 @@ void processGeom(Geometry *geo) {
|
||||
}
|
||||
}
|
||||
texconvf("Found %zu vertex duplicates, %.2f%%\n", dups, (float)dups/geo->numVertices*100);
|
||||
|
||||
for (int meshNum = 0; meshNum < n; meshNum++) {
|
||||
auto mesh = &meshes[meshNum];
|
||||
|
||||
@@ -5132,28 +5330,44 @@ void processGeom(Geometry *geo) {
|
||||
mesh->indices[i] = canonicalIdx[mesh->indices[i]];
|
||||
}
|
||||
|
||||
{
|
||||
indices Indices(mesh->indices, mesh->indices + mesh->numIndices);
|
||||
|
||||
auto clusters = processMeshWithClustering(mesh->indices, mesh->numIndices, geo->morphTargets[0].vertices, cosThreshold);
|
||||
for (auto&& cluster: clusters) {
|
||||
std::vector<uint16_t> idx;
|
||||
idx.reserve(cluster.faces.size()*3);
|
||||
for (auto && face: cluster.faces) {
|
||||
if (isDegenerateByIndex(mesh->indices[face*3 + 0], mesh->indices[face*3 + 1], mesh->indices[face*3 + 2])) {
|
||||
continue;
|
||||
}
|
||||
idx.push_back(mesh->indices[face*3 + 0]);
|
||||
idx.push_back(mesh->indices[face*3 + 1]);
|
||||
idx.push_back(mesh->indices[face*3 + 2]);
|
||||
}
|
||||
indices Indices(idx.begin(), idx.end());
|
||||
primitive_vector PrimitivesVector;
|
||||
tri_stripper TriStripper(Indices);
|
||||
|
||||
TriStripper.SetMinStripSize(0);
|
||||
TriStripper.SetCacheSize(0);
|
||||
TriStripper.SetBackwardSearch(true);
|
||||
|
||||
TriStripper.Strip(&pvecs[meshNum]);
|
||||
TriStripper.Strip(&PrimitivesVector);
|
||||
|
||||
pvecs[meshNum].push_back(PrimitivesVector);
|
||||
}
|
||||
pclus[meshNum] = clusters;
|
||||
|
||||
mesh->indices = oldIndices;
|
||||
mesh->numIndices = oldNumIndices;
|
||||
|
||||
for (auto &&strip: pvecs[meshNum]) {
|
||||
totalIndices += strip.Indices.size();
|
||||
if (strip.Type == TRIANGLES) {
|
||||
assert(strip.Indices.size()%3==0);
|
||||
strips += strip.Indices.size()/3;
|
||||
} else {
|
||||
strips ++;
|
||||
for (auto &&strip2: pvecs[meshNum]) {
|
||||
for (auto &&strip: strip2) {
|
||||
totalIndices += strip.Indices.size();
|
||||
if (strip.Type == TRIANGLES) {
|
||||
assert(strip.Indices.size()%3==0);
|
||||
strips += strip.Indices.size()/3;
|
||||
} else {
|
||||
strips ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5166,23 +5380,34 @@ void processGeom(Geometry *geo) {
|
||||
size_t meshVerticesCount = 0;
|
||||
size_t meshletIndexesCount = 0;
|
||||
size_t meshletVerticesCount = 0;
|
||||
|
||||
std::vector<std::vector<ConeClusterStrip>> meshConeClusterStrips(pvecs.size());
|
||||
|
||||
for (int pvn = 0; pvn < pvecs.size(); pvn++) {
|
||||
auto &&prims = pvecs[pvn];
|
||||
auto &&prims2 = pvecs[pvn];
|
||||
|
||||
std::set<uint16_t> meshletVertices;
|
||||
std::vector<primitive_group*> meshletStrips;
|
||||
std::list<ConeClusterStrip*> strips;
|
||||
std::vector<ConeClusterStrip*> meshletStrips;
|
||||
|
||||
std::list<primitive_group*> strips;
|
||||
for (auto &&strip: prims) {
|
||||
strips.push_back(&strip);
|
||||
for (int cvn = 0; cvn < prims2.size(); cvn++) {
|
||||
auto&& prims = prims2[cvn];
|
||||
|
||||
std::list<ConeClusterStrip> strips;
|
||||
for (auto &&strip: prims) {
|
||||
meshConeClusterStrips[pvn].push_back({&strip, &pclus[pvn][cvn]});
|
||||
}
|
||||
}
|
||||
|
||||
for (auto&& ccs: meshConeClusterStrips[pvn]) {
|
||||
strips.push_back(&ccs);
|
||||
}
|
||||
#undef printf
|
||||
|
||||
while(strips.size()) {
|
||||
for(;;) {
|
||||
// pluck strip with fewest new indices
|
||||
|
||||
primitive_group* bestStrip = nullptr;
|
||||
ConeClusterStrip* bestStrip = nullptr;
|
||||
|
||||
size_t remainingVertices = 128 - meshletVertices.size();
|
||||
size_t bestSharedVertices = 0;
|
||||
@@ -5191,7 +5416,7 @@ void processGeom(Geometry *geo) {
|
||||
auto &&strip = *strip_ptr;
|
||||
std::set<uint16_t> newVertices;
|
||||
size_t sharedVertices = 0;
|
||||
for (auto &&idx: strip.Indices) {
|
||||
for (auto &&idx: strip.strip->Indices) {
|
||||
if (meshletVertices.find(idx) == meshletVertices.end()) {
|
||||
newVertices.insert(idx);
|
||||
} else {
|
||||
@@ -5214,7 +5439,7 @@ void processGeom(Geometry *geo) {
|
||||
|
||||
// add strip to meshlet
|
||||
meshletStrips.push_back(bestStrip);
|
||||
for (auto &&idx: bestStrip->Indices) {
|
||||
for (auto &&idx: bestStrip->strip->Indices) {
|
||||
meshletVertices.insert(idx);
|
||||
}
|
||||
strips.remove(bestStrip);
|
||||
@@ -5224,7 +5449,7 @@ void processGeom(Geometry *geo) {
|
||||
|
||||
// printf("Meshlet constructed, %ld strips, %zu vertices\n", meshletStrips.size(), meshletVertices.size());
|
||||
for (auto &&strip: meshletStrips) {
|
||||
meshletIndexesCount += strip->Indices.size();
|
||||
meshletIndexesCount += strip->strip->Indices.size();
|
||||
}
|
||||
meshletVerticesCount += meshletVertices.size();
|
||||
|
||||
@@ -5242,10 +5467,13 @@ void processGeom(Geometry *geo) {
|
||||
}
|
||||
|
||||
std::set<uint16_t> meshVertices;
|
||||
for (auto &&strip: prims) {
|
||||
meshIndexesCount += strip.Indices.size();
|
||||
for (auto &&idx: strip.Indices) {
|
||||
meshVertices.insert(idx);
|
||||
for (int cvn = 0; cvn < prims2.size(); cvn++) {
|
||||
auto&& prims = prims2[cvn];
|
||||
for (auto &&strip: prims) {
|
||||
meshIndexesCount += strip.Indices.size();
|
||||
for (auto &&idx: strip.Indices) {
|
||||
meshVertices.insert(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
meshVerticesCount += meshVertices.size();
|
||||
@@ -5262,19 +5490,15 @@ void processGeom(Geometry *geo) {
|
||||
for (size_t i = 0; i < meshMeshlets.size(); i++) {
|
||||
auto &&mesh = meshMeshlets[i];
|
||||
|
||||
assert(mesh.size() <= 32767);
|
||||
meshData.write<int16_t>(mesh.size());
|
||||
assert(mesh.size() <= UINT32_MAX);
|
||||
meshData.write<uint32_t>(mesh.size());
|
||||
|
||||
assert((meshletData.size() + meshMeshlets.size() * 4) <= 32767);
|
||||
meshData.write<int16_t>(meshletData.size() + meshMeshlets.size() * 4);
|
||||
assert((meshletData.size() + meshMeshlets.size() * sizeof(MeshInfo)) <= UINT32_MAX);
|
||||
meshData.write<uint32_t>(meshletData.size() + meshMeshlets.size() * sizeof(MeshInfo));
|
||||
|
||||
for (auto && meshlet: mesh) {
|
||||
auto boundingSphere = meshlet.calculateBoundingSphere(vertices);
|
||||
|
||||
uint32_t totalIndexes = 0;
|
||||
for(auto&& strip: meshlet.strips) {
|
||||
totalIndexes += strip->Indices.size();
|
||||
}
|
||||
|
||||
// write out vertex data
|
||||
|
||||
@@ -5297,18 +5521,50 @@ void processGeom(Geometry *geo) {
|
||||
// write out index data
|
||||
meshlet.indexDataOffset = indexData.size();
|
||||
|
||||
for(auto&& strip: meshlet.strips) {
|
||||
if (strip->Type == TRIANGLES) {
|
||||
for (size_t i = 0; i < strip->Indices.size(); i+=3) {
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i]]);
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i+1]]);
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i+2]] | 128);
|
||||
std::map<ConeCluster*, std::vector<triangle_stripper::primitive_group*>> groupedStrips;
|
||||
for(auto&& clusterStrip: meshlet.strips) {
|
||||
groupedStrips[clusterStrip->cluster].push_back(clusterStrip->strip);
|
||||
}
|
||||
|
||||
size_t clusterCount = 0;
|
||||
|
||||
for(auto&& stripGroup: groupedStrips) {
|
||||
uint32_t totalIndexes = 256; // force a new cluster
|
||||
size_t totalIndexPatchPoint = 0;
|
||||
|
||||
for (auto&& strip: stripGroup.second) {
|
||||
if (totalIndexes + strip->Indices.size() > 255) {
|
||||
if (totalIndexPatchPoint) {
|
||||
assert(totalIndexes != 0);
|
||||
assert(totalIndexes <= 255);
|
||||
indexData[totalIndexPatchPoint] = totalIndexes;
|
||||
}
|
||||
totalIndexes = 0;
|
||||
clusterCount++;
|
||||
|
||||
indexData.write<int8_t>(stripGroup.first->normal.x * 127);
|
||||
indexData.write<int8_t>(stripGroup.first->normal.y * 127);
|
||||
indexData.write<int8_t>(stripGroup.first->normal.z * 127);
|
||||
totalIndexPatchPoint = indexData.size();
|
||||
indexData.write<uint8_t>(0);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < strip->Indices.size(); i++) {
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i]] | ((i + 1) == strip->Indices.size() ? 128 : 0));
|
||||
totalIndexes += strip->Indices.size();
|
||||
if (strip->Type == TRIANGLES) {
|
||||
for (size_t i = 0; i < strip->Indices.size(); i+=3) {
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i]]);
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i+1]]);
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i+2]] | 128);
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < strip->Indices.size(); i++) {
|
||||
indexData.write<uint8_t>(meshlet.vertexToLocalIndex[strip->Indices[i]] | ((i + 1) == strip->Indices.size() ? 128 : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(totalIndexPatchPoint != 0);
|
||||
assert(totalIndexes != 0);
|
||||
assert(totalIndexes <= 255);
|
||||
indexData[totalIndexPatchPoint] = totalIndexes;
|
||||
}
|
||||
|
||||
// write out skinning data
|
||||
@@ -5459,15 +5715,14 @@ void processGeom(Geometry *geo) {
|
||||
// write out meshlet data
|
||||
meshletData.write(boundingSphere);
|
||||
//isTextured, isNormaled, isColored, small_xyz, pad_xyz, small_uv
|
||||
uint16_t flags = texcoorded | (normaled << 1) | (colored << 2) | (!big_vertex << 3) | (pad_xyz << 4) | (!big_uv << 5);
|
||||
meshletData.write<uint16_t>(flags);
|
||||
meshletData.write<uint8_t>(0);
|
||||
//bool textured, bool normaled, bool colored, bool big_vertex, bool big_uv, bool pad_xyz
|
||||
uint8_t flags = texcoorded | (normaled << 1) | (colored << 2) | (!big_vertex << 3) | (pad_xyz << 4) | (!big_uv << 5);
|
||||
meshletData.write<uint8_t>(flags);
|
||||
assert(clusterCount <= 255);
|
||||
meshletData.write<uint8_t>(clusterCount);
|
||||
meshletData.write<uint8_t>(vertexSize);
|
||||
assert(meshlet.vertices.size() <= 65535);
|
||||
meshletData.write<uint16_t>(meshlet.vertices.size());
|
||||
assert(totalIndexes <= 65535);
|
||||
meshletData.write<uint16_t>(totalIndexes);
|
||||
//bool textured, bool normaled, bool colored, bool big_vertex, bool big_uv, bool pad_xyz
|
||||
assert(meshlet.vertices.size() <= 255);
|
||||
meshletData.write<uint8_t>(meshlet.vertices.size());
|
||||
meshlet.rewriteOffsetVDO = meshletData.size();
|
||||
meshletData.write<uint32_t>(meshlet.vertexDataOffset); // will be patched
|
||||
meshlet.rewriteOffsetIDO = meshletData.size();
|
||||
|
||||
Reference in New Issue
Block a user