Files
ImHex-Patterns/patterns/quantized-mesh.hexpat
applecuckoo bf94cb7243 patterns: Added new WebP and VGM patterns (#294)
* README: fix square bracket

* patterns: add WebP pattern

* patterns/dds: add x-dds mimetype

* patterns: add vgm pattern

* patterns/vgm: remove old pointer

* patterns/protobuf: fix field number handling

* patterns/protobuf: add .pb file extension

* patterns/uf2: updating the family IDs again

* patterns/png: add cHRM and tIME chunks

* patterns/png: whoops, old description snuck back in

* new quantized-mesh pattern

* add quantized-mesh to README, implement oct16 decoding
2024-11-17 13:53:18 +01:00

169 lines
3.6 KiB
Rust

#pragma author applecuckoo
#pragma description Cesium quantized-mesh terrain
#pragma endian little
// based on https://github.com/CesiumGS/quantized-mesh
// potential improvements: figure out high water mark encoding for indices
import std.math;
import std.io;
u8 extensionCount;
extensionCount = 0; // NOTE: set this to the amount of extensions in your terrain.
// ZigZag decoder based on protobuf.hexpat by WerWolv
struct ZigZag16 {
u16 value;
} [[sealed, format("format_zigzag16")]];
fn format_zigzag16(ZigZag16 zigzag) {
return s16((s16(zigzag.value) << 1) ^ (s16(zigzag.value) >> 15));
};
struct QuantizedMeshHeader {
double CenterX;
double CenterY;
double CenterZ;
float MinimumHeight;
float MaximumHeight;
double BoundingSphereCenterX;
double BoundingSphereCenterY;
double BoundingSphereCenterZ;
double BoundingSphereRadius;
double HorizonOcclusionPointX;
double HorizonOcclusionPointY;
double HorizonOcclusionPointZ;
};
struct VertexData {
u32 vertexCount;
ZigZag16 u[vertexCount];
ZigZag16 v[vertexCount];
ZigZag16 height[vertexCount];
};
struct IndexData16 {
u32 triangleCount;
u16 indices[triangleCount * 3];
};
struct IndexData32 {
u32 triangleCount;
u32 indices[triangleCount * 3];
};
struct EdgeIndices16 {
u32 westVertexCount;
u16 westIndices[westVertexCount];
u32 southVertexCount;
u16 southIndices[southVertexCount];
u32 eastVertexCount;
u16 eastIndices[eastVertexCount];
u32 northVertexCount;
u16 northIndices[northVertexCount];
};
struct EdgeIndices32 {
u32 westVertexCount;
u32 westIndices[westVertexCount];
u32 southVertexCount;
u32 southIndices[southVertexCount];
u32 eastVertexCount;
u32 eastIndices[eastVertexCount];
u32 northVertexCount;
u32 northIndices[northVertexCount];
};
enum ExtensionTypes : u8 {
OctEncodedVertexNormals = 0x1,
WaterMask,
Metadata = 0x4,
};
// Oct16 decode based on https://github.com/loicgasser/quantized-mesh-tile/blob/master/quantized_mesh_tile/utils.py
fn signNotZero(float v) {
if (v < 0.0)
return -1.0;
else
return 1.0;
};
fn fromSnorm(u8 value) {
return float(std::math::clamp(value, 0.0, 255.0) / 255.0 * 2.0 - 1.0);
};
struct Oct16 {
u8 x;
u8 y;
}[[sealed, format("format_oct16")]];
fn format_oct16(Oct16 oct) {
float xOut;
float yOut;
float zOut;
xOut = fromSnorm(oct.x);
yOut = fromSnorm(oct.y);
zOut = 1.0 - (std::math::abs(xOut) + std::math::abs(yOut));
if (zOut < 0.0) {
float oldX;
oldX = xOut;
xOut = (1.0 - std::math::abs(yOut)) * signNotZero(oldX);
yOut = (1.0 - std::math::abs(oldX)) * signNotZero(yOut);
}
return std::format("{}, {}, {}", xOut, yOut, zOut);
};
struct OctEncodedVertexNormals {
Oct16 xy[parent.parent.vertdata.vertexCount];
};
struct WaterMask {
u8 mask[parent.extensionLength];
};
struct Metadata {
u32 jsonLength;
char json[jsonLength];
};
struct ExtensionHeader {
u8 extensionId;
u32 extensionLength;
match (extensionId) {
(ExtensionTypes::OctEncodedVertexNormals): OctEncodedVertexNormals octVertNormals;
(ExtensionTypes::WaterMask): WaterMask maskData;
(ExtensionTypes::Metadata): Metadata metadata;
}
};
struct QuantizedMesh {
QuantizedMeshHeader header;
VertexData vertdata;
if (vertdata.vertexCount > 65536) {
IndexData32 indexdata;
EdgeIndices32 edgeindices;
} else {
IndexData16 indexdata;
EdgeIndices16 edgeindices;
}
ExtensionHeader extensions[extensionCount];
};
QuantizedMesh mesh @ 0x00;