njin
Engine 2D gọn nhẹ để tự tay làm game theo ý mình. Vibe coding cũng ổn luôn
Loading...
Searching...
No Matches
Animation 3D

Xương lò xo (tóc, đuôi, áo choàng) và chép animation sang bộ xương khác (retarget). Tiếp...

Classes

struct  njin::spring3d_chain
 Một chuỗi xương lò xo: xương bone và mọi xương nằm dưới nó (tóc, đuôi, râu, vạt áo). Tiếp...
struct  njin::spring3d_collider
 Một collider mà xương lò xo không xuyên qua (đầu, thân, vai), gắn vào một xương nên đi theo animation. Tiếp...
struct  njin::spring3d_desc
 Cách tạo một bộ xương lò xo. Tiếp...
struct  njin::retarget3d_desc
 Cách chép animation của model source sang model target có bộ xương khác: tên khác, tay chân dài ngắn khác. Tiếp...
struct  njin::foot3d_leg
 Một chân cho foot3d: đùi, cẳng chân, bàn chân (model_bone_find()). Tiếp...
struct  njin::foot3d_desc
 Cách tạo một bộ đặt chân. Tiếp...

Typedefs

using njin::foot3d_ground = std::function<bool(vec3 from, f32 distance, vec3 &point, vec3 &normal)>
 Mặt đất dưới một điểm, cho foot3d_update(): nhận điểm bắt đầu dò (thế giới) và quãng dò xuống; trả true và ghi point (điểm chạm) và normal (pháp tuyến) nếu có đất.

Các hàm

spring3d_handle njin::spring3d_create (context &ctx, const spring3d_desc &desc)
 Tạo một bộ xương lò xo cho một nhân vật.
i32 njin::spring3d_update (context &ctx, spring3d_handle handle, const model_pose &pose, const transform3d &transform, f32 dt, bone_pose3d *out, i32 count)
 Chạy lò xo dt giây và ghi tư thế cuối của mọi xương vào out: tư thế pose (animation, hay xương game đặt), với các xương lò xo đã trễ và đung đưa.
void njin::spring3d_reset (context &ctx, spring3d_handle handle)
 Đặt lại: lần spring3d_update() sau, mọi xương lò xo bắt đầu đứng yên ở tư thế của animation.
void njin::spring3d_destroy (context &ctx, spring3d_handle handle)
 Hủy bộ lò xo.
const char * njin::bone_humanoid_name (const char *name)
 Tên chuẩn của một xương người (humanoid) từ tên của nó trong file: hiểu cách đặt tên của Mixamo (mixamorig:LeftForeArm), Unreal (lowerarm_l, spine_02), Unity và VRM (LeftLowerArm, UpperChest) và Blender (forearm.L, thigh.R).
retarget3d_handle njin::retarget3d_create (context &ctx, const retarget3d_desc &desc)
 Chuẩn bị chép animation từ desc.source sang desc.target.
i32 njin::retarget3d_pose (const context &ctx, retarget3d_handle handle, const model_pose &pose, bone_pose3d *out, i32 count)
 Tư thế của model đích khi model nguồn ở tư thế pose.
i32 njin::retarget3d_source_bone (const context &ctx, retarget3d_handle handle, i32 bone)
 Xương nguồn được ghép với xương bone của model đích, để kiểm tra cách ghép.
void njin::retarget3d_destroy (context &ctx, retarget3d_handle handle)
 Hủy cách chép.
foot3d_handle njin::foot3d_create (context &ctx, const foot3d_desc &desc)
 Tạo một bộ đặt chân cho một nhân vật: mỗi frame, mỗi bàn chân của animation được đặt lên mặt đất ngay dưới nó (bậc thang, dốc, đá), hông hạ xuống cho bàn chân thấp hơn với tới, đầu gối gập bằng IK hai xương, lòng bàn chân nghiêng theo mặt đất.
i32 njin::foot3d_update (context &ctx, foot3d_handle handle, const model_pose &pose, const transform3d &transform, f32 dt, bone_pose3d *out, i32 count, f32 weight=1.0f)
 Đặt chân lên mặt đất và ghi tư thế cuối vào out, dò đất bằng physics3d_raycast() thẳng xuống dưới mỗi cổ chân (trúng body tĩnh, động, kinematic và height field của địa hình; không trúng nhân vật character3d).
i32 njin::foot3d_update (context &ctx, foot3d_handle handle, const model_pose &pose, const transform3d &transform, f32 dt, bone_pose3d *out, i32 count, const foot3d_ground &ground, f32 weight=1.0f)
 Như bản trên, nhưng mặt đất do game cho bằng ground (địa hình, lưới ô, bất kỳ hình gì không có trong physics3d).
f32 njin::foot3d_hip_offset (const context &ctx, foot3d_handle handle)
 Hông đang hạ bao nhiêu (đơn vị thế giới, âm là hạ xuống) sau lần foot3d_update() cuối, để camera hay vật cầm tay đi theo.
void njin::foot3d_reset (context &ctx, foot3d_handle handle)
 Đặt lại: lần foot3d_update() sau đặt chân ngay, không làm mượt từ chỗ cũ.
void njin::foot3d_destroy (context &ctx, foot3d_handle handle)
 Hủy bộ đặt chân.

Mô tả chi tiết

Xương lò xo (tóc, đuôi, áo choàng) và chép animation sang bộ xương khác (retarget).

Thông tin về Typedef

◆ foot3d_ground

using njin::foot3d_ground = std::function<bool(vec3 from, f32 distance, vec3 &point, vec3 &normal)>

Mặt đất dưới một điểm, cho foot3d_update(): nhận điểm bắt đầu dò (thế giới) và quãng dò xuống; trả true và ghi point (điểm chạm) và normal (pháp tuyến) nếu có đất.

Ví dụ trên địa hình: point = {p.x, terrain3d_height(ctx, t, p.x, p.z), p.z}.

Thông tin về hàm

◆ spring3d_create()

spring3d_handle njin::spring3d_create ( context & ctx,
const spring3d_desc & desc )

Tạo một bộ xương lò xo cho một nhân vật.

Mỗi nhân vật cần một bộ riêng (nó nhớ đầu các xương đang ở đâu); nhiều nhân vật dùng chung một model thì mỗi con một bộ.

const njin::spring3d_chain hair{.bone = njin::model_bone_find(ctx, girl, "hair_1"), .stiffness = 1.5f};
const njin::spring3d_collider head{.bone = njin::model_bone_find(ctx, girl, "head"), .offset = {0, 0.1f, 0},
.tail = {0, 0.1f, 0}, .radius = 0.11f};
njin::spring3d_handle springs = njin::spring3d_create(
ctx, {.model = girl, .chains = &hair, .chain_count = 1, .colliders = &head, .collider_count = 1});
i32 model_bone_find(const context &ctx, model_handle handle, const char *name)
Tìm xương theo tên (so đúng cả chuỗi).
spring3d_handle spring3d_create(context &ctx, const spring3d_desc &desc)
Tạo một bộ xương lò xo cho một nhân vật.
Một chuỗi xương lò xo: xương bone và mọi xương nằm dưới nó (tóc, đuôi, râu, vạt áo).
Definition njin_anim3d.h:16
Một collider mà xương lò xo không xuyên qua (đầu, thân, vai), gắn vào một xương nên đi theo animation...
Definition njin_anim3d.h:30
Các tham số
ctxContext của engine.
descModel, các chuỗi và collider.
Giá trị trả về
Handle; không hợp lệ nếu model không có xương hay không chuỗi nào có xương hợp lệ (cảnh báo nói vì sao). Giải phóng bằng spring3d_destroy().

◆ spring3d_update()

i32 njin::spring3d_update ( context & ctx,
spring3d_handle handle,
const model_pose & pose,
const transform3d & transform,
f32 dt,
bone_pose3d * out,
i32 count )

Chạy lò xo dt giây và ghi tư thế cuối của mọi xương vào out: tư thế pose (animation, hay xương game đặt), với các xương lò xo đã trễ và đung đưa.

Mô phỏng trong thế giới, theo transform của lần vẽ, nên nhân vật chạy thì tóc bay ra sau. Truyền out cho model_pose::bones để vẽ.

Gọi mỗi frame một lần cho mỗi nhân vật, trước khi vẽ. Lò xo chạy theo bước 1/60 giây (nhiều bước khi dt lớn, dt trên 0.1 giây bị cắt); dt 0 (game tạm dừng) không mô phỏng, chỉ đặt xương theo đầu xương hiện tại.

const njin::model_pose walk{.anim = walk_anim, .time = t};
njin::spring3d_update(ctx, springs, walk, at, dt, bones, 64);
njin::draw_model_anim(ctx, girl, at, {.anim = walk_anim, .time = t, .bones = bones});
void draw_model_anim(const context &ctx, model_handle handle, const transform3d &transform, const model_pose &pose, rgba tint=colors::white)
Vẽ model có xương ở tư thế pose.
i32 spring3d_update(context &ctx, spring3d_handle handle, const model_pose &pose, const transform3d &transform, f32 dt, bone_pose3d *out, i32 count)
Chạy lò xo dt giây và ghi tư thế cuối của mọi xương vào out: tư thế pose (animation,...
Một xương ở một tư thế: vị trí và ba trục của nó trong không gian của model (trước transform của lần ...
Definition njin_3d.h:771
Tư thế của một model có xương khi vẽ: animation nào, ở giây thứ mấy, và (tùy chọn) trộn với animation...
Definition njin_3d.h:620
Các tham số
ctxContext của engine.
handleBộ lò xo.
poseTư thế trước lò xo.
transformVị trí, hướng và tỉ lệ của lần vẽ (tỉ lệ nên đều ba trục).
dtThời gian trôi qua, giây (thường là delta()).
outMảng nhận model_bone_count() xương, trong không gian của model như model_bone_pose().
countSố phần tử của out.
Giá trị trả về
Số xương đã ghi; 0 nếu handle không hợp lệ hay count nhỏ hơn số xương.

◆ spring3d_reset()

void njin::spring3d_reset ( context & ctx,
spring3d_handle handle )

Đặt lại: lần spring3d_update() sau, mọi xương lò xo bắt đầu đứng yên ở tư thế của animation.

Gọi khi dịch chuyển tức thời nhân vật (hồi sinh, qua cổng), để tóc không bay theo cả quãng đường.

Các tham số
ctxContext của engine.
handleBộ lò xo.

◆ spring3d_destroy()

void njin::spring3d_destroy ( context & ctx,
spring3d_handle handle )

Hủy bộ lò xo.

Handle không hợp lệ bị bỏ qua.

Các tham số
ctxContext của engine.
handleBộ lò xo.

◆ bone_humanoid_name()

const char * njin::bone_humanoid_name ( const char * name)

Tên chuẩn của một xương người (humanoid) từ tên của nó trong file: hiểu cách đặt tên của Mixamo (mixamorig:LeftForeArm), Unreal (lowerarm_l, spine_02), Unity và VRM (LeftLowerArm, UpperChest) và Blender (forearm.L, thigh.R).

Kết quả là một trong: hips, spine, chest, upper_chest, neck, head, và theo hai bên (left_, right_): shoulder, upper_arm, lower_arm, hand, upper_leg, lower_leg, foot, toes, thumb_1..thumb_3, index_1..index_3, middle_1.., ring_1.., little_1.. (đốt ngón tính từ bàn tay).

Các tham số
nameTên xương.
Giá trị trả về
Tên chuẩn (chuỗi tĩnh), hoặc chuỗi rỗng nếu không nhận ra.

◆ retarget3d_create()

retarget3d_handle njin::retarget3d_create ( context & ctx,
const retarget3d_desc & desc )

Chuẩn bị chép animation từ desc.source sang desc.target.

Mỗi xương được ghép xoay so với tư thế gốc: xương đích xoay đúng góc mà xương nguồn xoay khỏi tư thế gốc của nó, trong không gian của model. Nên hai model cần cùng trục (cùng hướng lên, cùng hướng nhìn) và tư thế gốc giống nhau (cùng là chữ T hay cùng chữ A); nếu không, tay sẽ lệch đúng bằng độ lệch của hai tư thế gốc. Xương đích không được ghép đi theo xương cha của nó như ở tư thế gốc. Hông (hips) còn được dời theo hông nguồn, nhân với tỉ lệ độ cao hông (chiều dài chân) của hai model, nên người lùn bước ngắn hơn và chân không trượt.

Các tham số
ctxContext của engine.
descHai model và cách ghép xương.
Giá trị trả về
Handle; không hợp lệ nếu một model không có xương hay không xương nào ghép được (cảnh báo nói vì sao). Giải phóng bằng retarget3d_destroy().

◆ retarget3d_pose()

i32 njin::retarget3d_pose ( const context & ctx,
retarget3d_handle handle,
const model_pose & pose,
bone_pose3d * out,
i32 count )

Tư thế của model đích khi model nguồn ở tư thế pose.

Truyền out cho model_pose::bones khi vẽ model đích.

njin::retarget3d_pose(ctx, to_dwarf, {.anim = run, .time = t}, bones, 80);
njin::draw_model_anim(ctx, dwarf, at, {.bones = bones});
i32 retarget3d_pose(const context &ctx, retarget3d_handle handle, const model_pose &pose, bone_pose3d *out, i32 count)
Tư thế của model đích khi model nguồn ở tư thế pose.
void run(context &ctx)
Chạy vòng lặp chính cho đến khi cửa sổ đóng.
Các tham số
ctxContext của engine.
handleCách chép.
poseTư thế của model nguồn (animation của nó, hay xương game đặt).
outMảng nhận model_bone_count() xương của model đích, như model_bone_pose().
countSố phần tử của out.
Giá trị trả về
Số xương đã ghi; 0 nếu handle không hợp lệ hay count nhỏ hơn số xương.

◆ retarget3d_source_bone()

i32 njin::retarget3d_source_bone ( const context & ctx,
retarget3d_handle handle,
i32 bone )

Xương nguồn được ghép với xương bone của model đích, để kiểm tra cách ghép.

Các tham số
ctxContext của engine.
handleCách chép.
boneXương của model đích, 0..model_bone_count() - 1.
Giá trị trả về
Xương của model nguồn, hoặc -1 nếu bone không được ghép hay handle không hợp lệ.

◆ retarget3d_destroy()

void njin::retarget3d_destroy ( context & ctx,
retarget3d_handle handle )

Hủy cách chép.

Handle không hợp lệ bị bỏ qua.

Các tham số
ctxContext của engine.
handleCách chép.

◆ foot3d_create()

foot3d_handle njin::foot3d_create ( context & ctx,
const foot3d_desc & desc )

Tạo một bộ đặt chân cho một nhân vật: mỗi frame, mỗi bàn chân của animation được đặt lên mặt đất ngay dưới nó (bậc thang, dốc, đá), hông hạ xuống cho bàn chân thấp hơn với tới, đầu gối gập bằng IK hai xương, lòng bàn chân nghiêng theo mặt đất.

Bàn chân đang nhấc trong animation (bước đi) vẫn nhấc, cao hơn mặt đất dưới nó bấy nhiêu. Mỗi nhân vật một bộ (nó nhớ độ cao để làm mượt).

Các tham số
ctxContext của engine.
descModel và các chân.
Giá trị trả về
Handle; không hợp lệ nếu model không có xương hay không chân nào đủ ba xương (cảnh báo nói vì sao). Giải phóng bằng foot3d_destroy().

◆ foot3d_update() [1/2]

i32 njin::foot3d_update ( context & ctx,
foot3d_handle handle,
const model_pose & pose,
const transform3d & transform,
f32 dt,
bone_pose3d * out,
i32 count,
f32 weight = 1.0f )

Đặt chân lên mặt đất và ghi tư thế cuối vào out, dò đất bằng physics3d_raycast() thẳng xuống dưới mỗi cổ chân (trúng body tĩnh, động, kinematic và height field của địa hình; không trúng nhân vật character3d).

Thứ tự với các bước khác: retarget3d_pose() trước (nếu có), rồi foot3d_update() với pose.bones là kết quả đó, rồi spring3d_update() với pose.bones là kết quả của foot3d, rồi vẽ. Gốc của lần vẽ (transform) là chỗ nhân vật đứng (đáy capsule của character3d).

njin::foot3d_update(ctx, feet, {.anim = idle, .time = t}, at, dt, bones, 64);
njin::draw_model_anim(ctx, hero, at, {.bones = bones});
i32 foot3d_update(context &ctx, foot3d_handle handle, const model_pose &pose, const transform3d &transform, f32 dt, bone_pose3d *out, i32 count, f32 weight=1.0f)
Đặt chân lên mặt đất và ghi tư thế cuối vào out, dò đất bằng physics3d_raycast() thẳng xuống dưới mỗi...
Các tham số
ctxContext của engine.
handleBộ đặt chân.
poseTư thế trước khi đặt chân (animation, hay xương đã tính).
transformVị trí, hướng và tỉ lệ của lần vẽ (tỉ lệ nên đều ba trục).
dtThời gian trôi qua, giây, để làm mượt. 0: đặt ngay, không làm mượt.
outMảng nhận model_bone_count() xương, như model_bone_pose().
countSố phần tử của out.
weightMức áp, 0..1: 0 là đúng animation, 1 là chân đặt hẳn lên đất (giảm dần khi nhân vật nhảy lên).
Giá trị trả về
Số xương đã ghi; 0 nếu handle không hợp lệ hay count nhỏ hơn số xương.

◆ foot3d_update() [2/2]

i32 njin::foot3d_update ( context & ctx,
foot3d_handle handle,
const model_pose & pose,
const transform3d & transform,
f32 dt,
bone_pose3d * out,
i32 count,
const foot3d_ground & ground,
f32 weight = 1.0f )

Như bản trên, nhưng mặt đất do game cho bằng ground (địa hình, lưới ô, bất kỳ hình gì không có trong physics3d).

Các tham số
ctxContext của engine.
handleBộ đặt chân.
poseTư thế trước khi đặt chân.
transformVị trí, hướng và tỉ lệ của lần vẽ.
dtThời gian trôi qua, giây.
outMảng nhận model_bone_count() xương.
countSố phần tử của out.
groundHàm dò mặt đất.
weightMức áp, 0..1.
Giá trị trả về
Số xương đã ghi.

◆ foot3d_hip_offset()

f32 njin::foot3d_hip_offset ( const context & ctx,
foot3d_handle handle )

Hông đang hạ bao nhiêu (đơn vị thế giới, âm là hạ xuống) sau lần foot3d_update() cuối, để camera hay vật cầm tay đi theo.

Các tham số
ctxContext của engine.
handleBộ đặt chân.
Giá trị trả về
Độ dời.

◆ foot3d_reset()

void njin::foot3d_reset ( context & ctx,
foot3d_handle handle )

Đặt lại: lần foot3d_update() sau đặt chân ngay, không làm mượt từ chỗ cũ.

Gọi khi dịch chuyển tức thời nhân vật.

Các tham số
ctxContext của engine.
handleBộ đặt chân.

◆ foot3d_destroy()

void njin::foot3d_destroy ( context & ctx,
foot3d_handle handle )

Hủy bộ đặt chân.

Handle không hợp lệ bị bỏ qua.

Các tham số
ctxContext của engine.
handleBộ đặt chân.