#pragma once
#include <span>
#include <vector>
#include <whiteout/common_types.h>
#include <whiteout/compatibility.h>
#include <whiteout/models/gltf/gltf.h>
namespace whiteout {
namespace models {
namespace wem {
namespace gltf_detail {
struct BinBuilder {
std::vector<u8> bytes;
u32 append(const void* data, std::size_t size) {
while (bytes.size() % 4 != 0) {
bytes.push_back(0);
}
const u32 offset = static_cast<u32>(bytes.size());
const u8* raw = static_cast<const u8*>(data);
bytes.insert(bytes.end(), raw, raw + size);
return offset;
}
};
inline u32 AddView(gltf::Asset& asset, BinBuilder& bin, const void* data, std::size_t size,
gltf::BufferTarget target) {
gltf::BufferView view;
view.buffer = 0;
view.byteOffset = bin.append(data, size);
view.byteLength = static_cast<u32>(size);
view.target = target;
asset.bufferViews.push_back(view);
return static_cast<u32>(asset.bufferViews.size() - 1);
}
inline u32 AddFloatAccessor(gltf::Asset& asset, BinBuilder& bin, std::span<const f32> values,
u32 components, gltf::AccessorType type, bool withBounds,
gltf::BufferTarget target = gltf::BufferTarget::ArrayBuffer) {
const u32 count = static_cast<u32>(values.size() / components);
const u32 view = AddView(asset, bin, values.data(), values.size() * sizeof(f32), target);
gltf::Accessor accessor;
accessor.bufferView = view;
accessor.componentType = gltf::ComponentType::F32;
accessor.count = count;
accessor.type = type;
if (withBounds && count > 0) {
accessor.min.assign(components, 0.0);
accessor.max.assign(components, 0.0);
for (u32 c = 0; c < components; ++c) {
accessor.min[c] = values[c];
accessor.max[c] = values[c];
}
for (u32 i = 1; i < count; ++i) {
for (u32 c = 0; c < components; ++c) {
const f64 value = values[static_cast<std::size_t>(i) * components + c];
if (value < accessor.min[c]) {
accessor.min[c] = value;
}
if (value > accessor.max[c]) {
accessor.max[c] = value;
}
}
}
}
asset.accessors.push_back(std::move(accessor));
return static_cast<u32>(asset.accessors.size() - 1);
}
inline Vector3f PermuteToGltf(const Vector3f& v) {
return {v.y, v.z, v.x};
}
inline Quaternion PermuteToGltf(const Quaternion& q) {
return {q.y, q.z, q.x, q.w};
}
} } } }