365 lines
13 KiB
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");
|