Backlog/lib/ozz/src/ozz.zig

365 lines
13 KiB
Zig

pub fn hello() void {
std.debug.print("whatsup\n", .{});
}
pub const Skeleton = opaque {
pub fn create() *@This() {
return @ptrCast(CreateSkeleton_c());
}
// todo add error messages
pub fn loadFromFile(self: *@This(), path: [*c]const u8) void {
LoadSkeletonFromFile_c(self, path);
}
pub fn loadFromBytes(self: *@This(), bytes: []const u8) void {
LoadSkeletonFromBytes_c(self, @constCast(@ptrCast(bytes.ptr)), bytes.len);
}
pub fn getJointsList(self: *@This()) []const [*c]const u8 {
const span: Span([*c]const u8) = @bitCast(SkeletonGetJointsList_c(@ptrCast(self)));
// std.debug.print("{d} \n", .{@intFromPtr(span.end)});
return span.toSlice();
}
pub fn getRestPoseModel(self: *@This()) Span(SoaTransform) {
return @bitCast(SkeletonJointRestPoses_c(@ptrCast(self)));
}
pub fn numSoaJoints(self: *@This()) usize {
return @intCast(SkeletonNumSoaJoints_c(@ptrCast(self)));
}
pub fn numJoints(self: *@This()) usize {
return @intCast(SkeletonNumJoints_c(@ptrCast(self)));
}
pub fn destroy(self: *@This()) void {
DestroySkeleton_c(@ptrCast(self));
}
pub extern fn SkeletonJointRestPoses_c(s: ?*anyopaque) callconv(.C) OpaqueSpan;
pub extern fn SkeletonNumJoints_c(s: ?*anyopaque) callconv(.C) c_int;
pub extern fn SkeletonNumSoaJoints_c(s: ?*anyopaque) callconv(.C) c_int;
pub extern fn SkeletonGetJointsList_c(s: ?*anyopaque) callconv(.C) OpaqueSpan;
pub extern fn CreateSkeleton_c() callconv(.C) ?*anyopaque;
pub extern fn DestroySkeleton_c(target: ?*anyopaque) callconv(.C) void;
pub extern fn LoadSkeletonFromFile_c(s: ?*anyopaque, path: [*c]const u8) callconv(.C) void;
pub extern fn LoadSkeletonFromBytes_c(s: ?*anyopaque, size: ?*anyopaque, size: usize) void;
};
pub const Animation = opaque {
pub fn create() *@This() {
return @ptrCast(CreateAnimation_c());
}
// todo add error messages
pub fn loadFromFile(self: *@This(), path: [*c]const u8) void {
LoadAnimationFromFile_c(self, path);
}
pub fn loadFromBytes(self: *@This(), bytes: []const u8) void {
LoadAnimationFromBytes_c(self, @constCast(@ptrCast(bytes.ptr)), bytes.len);
}
pub fn destroy(self: *@This()) void {
DestroyAnimation_c(@ptrCast(self));
}
pub fn getDuration(self: *@This()) f32 {
return AnimationGetDuration_c(@ptrCast(self));
}
pub extern fn AnimationGetDuration_c(s: ?*anyopaque) callconv(.C) f32;
pub extern fn CreateAnimation_c() callconv(.C) ?*anyopaque;
pub extern fn LoadAnimationFromFile_c(s: ?*anyopaque, path: [*c]const u8) void;
pub extern fn LoadAnimationFromBytes_c(s: ?*anyopaque, size: ?*anyopaque, size: usize) void;
pub extern fn DestroyAnimation_c(target: ?*anyopaque) callconv(.C) void;
};
pub const SamplingJob = extern struct {
ratio: f32 = 0.0, // float ratio;
animation: ?*Animation = undefined, // const Animation* animation;
context: ?*SamplingJobContext = undefined, //
output: Span(SoaTransform) = .{}, // ozz::span<SoaTransform>
pub fn run(self: *@This()) bool {
return SamplingJob_Run_c(@ptrCast(self));
}
pub fn validate(self: *@This()) bool {
return SamplingJob_Validate_c(@ptrCast(self));
}
pub extern fn SamplingJob_Validate_c(*anyopaque) bool;
pub extern fn SamplingJob_Run_c(*anyopaque) bool;
};
pub fn spanFromArrayList(list: anytype) Span(@TypeOf(list.items[0])) {
return makeSpan(list.items);
}
pub fn makeSpan(slice: anytype) Span(@TypeOf(slice[0])) {
//return .{ .start = slice.ptr, .end = slice.ptr + slice.len };
return .{ .start = slice.ptr, .end = slice.len };
}
pub fn Span(comptime T: type) type {
return extern struct {
start: [*c]T = null,
end: [*c]T = null,
pub fn fromArray(arr: []T) @This() {
//return .{ .start = arr.ptr, .end = arr.ptr + arr.len };
return .{ .start = arr.ptr, .end = arr.len };
}
pub fn toSlice(self: @This()) []T {
return self.start[0..(@intFromPtr(self.end))];
}
};
}
pub const SamplingJobContext = opaque {
pub fn create() *@This() {
return @ptrCast(CreateSamplingJobContext_c());
}
pub fn createMaxTracks(tracksCount: c_int) *@This() {
return @ptrCast(CreateSamplingJobContextCount_c(tracksCount));
}
pub fn resize(self: *@This(), tracksCount: usize) void {
SamplingJobContext_Resize_c(@ptrCast(self), @intCast(tracksCount));
}
pub fn invalidate(self: *@This()) void {
SamplingJobContext_Invalidate_c(self);
}
pub fn maxTracks(self: *@This()) c_int {
return SamplingJobContext_MaxTracks_c(@ptrCast(self));
}
pub fn maxSoaTracks(self: *@This()) c_int {
return SamplingJobContext_MaxSoaTracks_c(@ptrCast(self));
}
pub fn destroy(self: *@This()) void {
DestroySamplingJobContext_c(self);
}
pub extern fn CreateSamplingJobContextCount_c(c_int) callconv(.C) ?*anyopaque;
pub extern fn CreateSamplingJobContext_c() callconv(.C) ?*anyopaque;
pub extern fn DestroySamplingJobContext_c(?*anyopaque) callconv(.C) void;
pub extern fn SamplingJobContext_Resize_c(?*anyopaque, c_int) callconv(.C) void;
pub extern fn SamplingJobContext_Invalidate_c(?*anyopaque) callconv(.C) void;
pub extern fn SamplingJobContext_MaxTracks_c(?*anyopaque) callconv(.C) c_int;
pub extern fn SamplingJobContext_MaxSoaTracks_c(?*anyopaque) callconv(.C) c_int;
};
pub extern fn testFunc() callconv(.C) void;
pub extern fn startupOzz() callconv(.C) void;
pub extern fn shutdownOzz() callconv(.C) void;
pub const SimdFloat4 = @Vector(4, f32);
pub const Float4x4 = extern struct {
cols: [4]SimdFloat4,
};
pub const SimdFloat4_one = .{ 1, 1, 1, 1 };
pub const SimdFloat4_zero = .{ 0, 0, 0, 0 };
pub const SoaFloat2 = extern struct {
x: SimdFloat4 = undefined,
y: SimdFloat4 = undefined,
};
pub const SoaFloat3 = extern struct {
x: SimdFloat4 = undefined,
y: SimdFloat4 = undefined,
z: SimdFloat4 = undefined,
pub fn zero() @This() {
return .{
.x = SimdFloat4_zero,
.y = SimdFloat4_zero,
.z = SimdFloat4_zero,
};
}
pub fn one() @This() {
return .{
.x = SimdFloat4_one,
.y = SimdFloat4_one,
.z = SimdFloat4_one,
};
}
};
pub const SoaQuaternion = extern struct {
x: SimdFloat4 = undefined,
y: SimdFloat4 = undefined,
z: SimdFloat4 = undefined,
w: SimdFloat4 = undefined,
pub fn identity() @This() {
return .{
.x = SimdFloat4_zero,
.y = SimdFloat4_zero,
.z = SimdFloat4_zero,
.w = SimdFloat4_one,
};
}
};
pub const OpaqueSpan = extern struct {
start: ?*anyopaque,
end: ?*anyopaque,
};
pub const SoaTransform = extern struct {
translation: SoaFloat3 = SoaFloat3.zero(),
rotation: SoaQuaternion = SoaQuaternion.identity(),
scale: SoaFloat3 = SoaFloat3.one(),
};
pub const kNoParent = -1;
pub const kMaxJoints = 1024;
pub const kMaxSoAJoints = (kMaxJoints + 3) / 4;
pub const LocalToModelJob = extern struct {
// The Skeleton object describing the joint hierarchy used for local to
// model space conversion.
skeleton: ?*Skeleton,
// The root matrix will multiply to every model space matrices, default nullptr
// means an identity matrix. This can be used to directly compute world-space
// transforms for example.
root: ?*Float4x4 = null,
// Defines "from" which joint the local-to-model conversion should start.
// Default value is ozz::Skeleton::kNoParent, meaning the whole hierarchy is
// updated. This parameter can be used to optimize update by limiting
// conversion to part of the joint hierarchy. Note that "from" parent should
// be a valid matrix, as it is going to be used as part of "from" joint
// hierarchy update.
from: c_int = kNoParent,
// Defines "to" which joint the local-to-model conversion should go, "to"
// included. Update will end before "to" joint is reached if "to" is not part
// of the hierarchy starting from "from". Default value is
// ozz::animation::Skeleton::kMaxJoints, meaning the hierarchy (starting from
// "from") is updated to the last joint.
to: c_int = kMaxJoints,
// If true, "from" joint is not updated during job execution. Update starts
// with all children of "from". This can be used to update a model-space
// transform independently from the local-space one. To do so: set "from"
// joint model-space transform matrix, and run this Job with "from_excluded"
// to update all "from" children.
// Default value is false.
from_excluded: bool = false,
// The input range that store local transforms.
input: Span(SoaTransform),
// Job output.
// The output range to be filled with model-space matrices.
output: Span(Float4x4),
pub fn run(self: *@This()) bool {
return LocalToModelJob_Run_c(@ptrCast(self));
}
pub extern fn LocalToModelJob_Run_c(?*anyopaque) callconv(.C) bool;
};
pub const Layer = extern struct {
// Blending weight of this layer. Negative values are considered as 0.
// Normalization is performed during the blending stage so weight can be in
// any range, even though range [0:1] is optimal.
weight: f32 = 0.0,
// The range [begin,end[ of input layer posture. This buffer expect to store
// local space transforms, that are usually outputted from a sampling job.
// This range must be at least as big as the rest pose buffer, even though
// only the number of transforms defined by the rest pose buffer will be
// processed.
transform: Span(SoaTransform) = .{},
// Optional range [begin,end[ of blending weight for each joint in this
// layer.
// If both pointers are nullptr (default case) then per joint weight
// blending is disabled. A valid range is defined as being at least as big
// as the rest pose buffer, even though only the number of transforms
// defined by the rest pose buffer will be processed. When a layer doesn't
// specifies per joint weights, then it is implicitly considered as
// being 1.f. This default value is a reference value for the normalization
// process, which implies that the range of values for joint weights should
// be [0,1]. Negative weight values are considered as 0, but positive ones
// aren't clamped because they could exceed 1.f if all layers contains valid
// joint weights.
jointWeights: Span(SoaTransform) = .{},
};
pub const BlendingJob = extern struct {
// The job blends the rest pose to the output when the accumulated weight of
// all layers is less than this threshold value.
// Must be greater than 0.f.
threshold: f32 = 0.01,
// Job input layers, can be empty or nullptr.
// The range of layers that must be blended.
layers: Span(Layer) = .{},
// Job input additive layers, can be empty or nullptr.
// The range of layers that must be added to the output.
additive_layers: Span(Layer) = .{},
// The skeleton rest pose. The size of this buffer defines the number of
// transforms to blend. This is the reference because this buffer is defined
// by the skeleton that all the animations belongs to.
// It is used when the accumulated weight for a bone on all layers is
// less than the threshold value, in order to fall back on valid transforms.
rest_pose: Span(SoaTransform) = .{},
// Job output.
// The range of output transforms to be filled with blended layer
// transforms during job execution.
// Must be at least as big as the rest pose buffer, but only the number of
// transforms defined by the rest pose buffer size will be processed.
output: Span(SoaTransform) = .{},
// Validates job parameters.
// Returns true for a valid job, false otherwise:
// -if layer range is not valid (can be empty though).
// -if additive layer range is not valid (can be empty though).
// -if any layer is not valid.
// -if output range is not valid.
// -if any buffer (including layers' content : transform, joint weights...) is
// smaller than the rest pose buffer.
// -if the threshold value is less than or equal to 0.f.
pub fn validate(self: *const @This()) bool {
return self.BlendingJob_Validate_c(@ptrCast(self));
}
// Runs job's blending task.
// The job is validated before any operation is performed, see Validate() for
// more details.
// Returns false if *this job is not valid.
pub fn run(self: *@This()) bool {
return BlendingJob_Run_c(@ptrCast(self));
}
pub extern fn BlendingJob_Validate_c(?*anyopaque) callconv(.C) bool;
pub extern fn BlendingJob_Run_c(?*anyopaque) callconv(.C) bool;
};
pub const std = @import("std");