Merge branch 'master' into GPU_SKIN_ON_BY_DEFAULT
This commit is contained in:
commit
7905bc1234
76 changed files with 30760 additions and 9200 deletions
110
src/rmodels.c
110
src/rmodels.c
|
|
@ -50,9 +50,9 @@
|
|||
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||
#include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality
|
||||
|
||||
#include <stdio.h> // Required for: sprintf()
|
||||
#include <stdio.h> // Required for: sprintf(), snprintf()
|
||||
#include <stdlib.h> // Required for: malloc(), calloc(), free()
|
||||
#include <string.h> // Required for: memcmp(), strlen(), strncpy()
|
||||
#include <string.h> // Required for: strlen(), memcmp()
|
||||
#include <math.h> // Required for: sinf(), cosf(), sqrtf(), fabsf()
|
||||
|
||||
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
||||
|
|
@ -503,7 +503,7 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
|
|||
rlBegin(RL_TRIANGLES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
float ringangle = DEG2RAD*(180.0f/(rings + 1)); // Angle between latitudinal parallels
|
||||
float ringangle = DEG2RAD*(180.0f/rings); // Angle between latitudinal parallels
|
||||
float sliceangle = DEG2RAD*(360.0f/slices); // Angle between longitudinal meridians
|
||||
|
||||
float cosring = cosf(ringangle);
|
||||
|
|
@ -515,7 +515,7 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
|
|||
vertices[2] = (Vector3){ 0, 1, 0 };
|
||||
vertices[3] = (Vector3){ sinring, cosring, 0 };
|
||||
|
||||
for (int i = 0; i < rings + 1; i++)
|
||||
for (int i = 0; i < rings; i++)
|
||||
{
|
||||
for (int j = 0; j < slices; j++)
|
||||
{
|
||||
|
|
@ -557,31 +557,42 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
|
|||
rlBegin(RL_LINES);
|
||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
for (int i = 0; i < (rings + 2); i++)
|
||||
float ringangle = DEG2RAD*(180.0f/rings); // Angle between latitudinal parallels
|
||||
float sliceangle = DEG2RAD*(360.0f/slices); // Angle between longitudinal meridians
|
||||
|
||||
float cosring = cosf(ringangle);
|
||||
float sinring = sinf(ringangle);
|
||||
float cosslice = cosf(sliceangle);
|
||||
float sinslice = sinf(sliceangle);
|
||||
|
||||
Vector3 vertices[4] = { 0 }; // Required to store face vertices
|
||||
vertices[2] = (Vector3){ 0, 1, 0 };
|
||||
vertices[3] = (Vector3){ sinring, cosring, 0 };
|
||||
|
||||
for (int i = 0; i < rings; i++)
|
||||
{
|
||||
for (int j = 0; j < slices; j++)
|
||||
{
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
|
||||
vertices[0] = vertices[2]; // Rotate around y axis to set up vertices for next face
|
||||
vertices[1] = vertices[3];
|
||||
vertices[2] = (Vector3){ cosslice*vertices[2].x - sinslice*vertices[2].z, vertices[2].y, sinslice*vertices[2].x + cosslice*vertices[2].z }; // Rotation matrix around y axis
|
||||
vertices[3] = (Vector3){ cosslice*vertices[3].x - sinslice*vertices[3].z, vertices[3].y, sinslice*vertices[3].x + cosslice*vertices[3].z };
|
||||
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*(j + 1)/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*(j + 1)/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));
|
||||
// Longitude Lines
|
||||
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||
rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z);
|
||||
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*sinf(DEG2RAD*(360.0f*j/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1))),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*(i + 1)))*cosf(DEG2RAD*(360.0f*j/slices)));
|
||||
rlVertex3f(cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*sinf(DEG2RAD*(360.0f*j/slices)),
|
||||
sinf(DEG2RAD*(270 + (180.0f/(rings + 1))*i)),
|
||||
cosf(DEG2RAD*(270 + (180.0f/(rings + 1))*i))*cosf(DEG2RAD*(360.0f*j/slices)));
|
||||
// Latitude Lines
|
||||
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||
rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z);
|
||||
|
||||
// Diagonal Lines
|
||||
rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z);
|
||||
rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z);
|
||||
}
|
||||
|
||||
vertices[2] = vertices[3]; // Rotate around z axis to set up starting vertices for next ring
|
||||
vertices[3] = (Vector3){ cosring*vertices[3].x + sinring*vertices[3].y, -sinring*vertices[3].x + cosring*vertices[3].y, vertices[3].z }; // Rotation matrix around z axis
|
||||
}
|
||||
rlEnd();
|
||||
rlPopMatrix();
|
||||
|
|
@ -2088,7 +2099,7 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
|||
|
||||
// Get file name from path and convert variable name to uppercase
|
||||
char varFileName[256] = { 0 };
|
||||
strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); // NOTE: Using function provided by [rcore] module
|
||||
snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module
|
||||
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
|
||||
|
||||
// Add image information
|
||||
|
|
@ -2333,7 +2344,7 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, float frame)
|
|||
Matrix currentPoseMatrix = { 0 };
|
||||
|
||||
// Update all bones and bone matrices of model
|
||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
{
|
||||
// Compute interpolated pose between current and next frame
|
||||
// NOTE: Storing animation frame data in model.currentPose
|
||||
|
|
@ -2413,7 +2424,7 @@ void UpdateModelAnimationBonesEx(Model model, ModelAnimation animA, float frameA
|
|||
Matrix bindPoseMatrix = { 0 };
|
||||
Matrix currentPoseMatrix = { 0 };
|
||||
|
||||
for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++)
|
||||
{
|
||||
// Get frame-interpolation for first animation
|
||||
Vector3 frameATranslation = Vector3Lerp(
|
||||
|
|
@ -3189,6 +3200,8 @@ Mesh GenMeshCone(float radius, float height, int slices)
|
|||
}
|
||||
|
||||
// Generate torus mesh
|
||||
// NOTE: The distance between the center of the hole and the center of the
|
||||
// tube is half size of the radius of the tube (radius*size/2)
|
||||
Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
|
||||
{
|
||||
Mesh mesh = { 0 };
|
||||
|
|
@ -4466,7 +4479,7 @@ static Model LoadOBJ(const char *fileName)
|
|||
}
|
||||
|
||||
char currentDir[MAX_FILEPATH_LENGTH] = { 0 };
|
||||
strncpy(currentDir, GetWorkingDirectory(), MAX_FILEPATH_LENGTH - 1); // Save current working directory
|
||||
snprintf(currentDir, MAX_FILEPATH_LENGTH, "%s", GetWorkingDirectory()); // Save current working directory
|
||||
const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness
|
||||
if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir);
|
||||
|
||||
|
|
@ -5051,7 +5064,7 @@ static Model LoadIQM(const char *fileName)
|
|||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
|
||||
UnloadFileData(fileData);
|
||||
|
||||
|
|
@ -5279,7 +5292,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
|
|||
// Build frameposes
|
||||
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++)
|
||||
{
|
||||
for (int i = 0; i < animations[a].boneCount; i++)
|
||||
for (unsigned int i = 0; i < animations[a].boneCount; i++)
|
||||
{
|
||||
if (bones[i].parent >= 0)
|
||||
{
|
||||
|
|
@ -5354,8 +5367,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||
{
|
||||
int base64Size = (int)strlen(cgltfImage->uri + i + 1);
|
||||
while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings
|
||||
int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
||||
int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes
|
||||
int numberOfEncodedBits = base64Size*6 - (base64Size*6)%8; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits
|
||||
int outSize = numberOfEncodedBits >> 3; // Actual encoded bytes
|
||||
void *data = NULL;
|
||||
|
||||
cgltf_options options = { 0 };
|
||||
|
|
@ -5407,15 +5420,15 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
|
|||
}
|
||||
|
||||
// Load bone info from GLTF skin data
|
||||
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount)
|
||||
static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount)
|
||||
{
|
||||
*boneCount = (int)skin.joints_count;
|
||||
*boneCount = (unsigned int)skin.joints_count;
|
||||
BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo));
|
||||
|
||||
for (unsigned int i = 0; i < skin.joints_count; i++)
|
||||
{
|
||||
cgltf_node node = *skin.joints[i];
|
||||
if (node.name != NULL) strncpy(bones[i].name, node.name, sizeof(bones[i].name) - 1);
|
||||
if (node.name != NULL) snprintf(bones[i].name, sizeof(bones[i].name), "%s", node.name);
|
||||
|
||||
// Find parent bone index by walking up the node tree past any
|
||||
// non-joint ancestors (intermediate transform nodes used by some
|
||||
|
|
@ -6182,7 +6195,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount);
|
||||
model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
|
||||
for (int i = 0; i < model.skeleton.boneCount; i++)
|
||||
for (unsigned int i = 0; i < model.skeleton.boneCount; i++)
|
||||
{
|
||||
Matrix bindMatrix = { 0 };
|
||||
cgltf_float inverseBindTransform[16] = { 0 };
|
||||
|
|
@ -6347,7 +6360,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL))
|
||||
{
|
||||
int parentBoneId = -1;
|
||||
for (int joint = 0; joint < model.skeleton.boneCount; joint++)
|
||||
for (unsigned int joint = 0; joint < model.skeleton.boneCount; joint++)
|
||||
{
|
||||
if (data->skins[0].joints[joint] == node->parent)
|
||||
{
|
||||
|
|
@ -6378,7 +6391,7 @@ static Model LoadGLTF(const char *fileName)
|
|||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
// Free unused allocated memory in case of no bones defined
|
||||
|
|
@ -6634,7 +6647,6 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
cgltf_animation_channel *translate;
|
||||
cgltf_animation_channel *rotate;
|
||||
cgltf_animation_channel *scale;
|
||||
cgltf_interpolation_type interpolationType;
|
||||
};
|
||||
|
||||
struct Channels *boneChannels = (struct Channels *)RL_CALLOC(animations[a].boneCount, sizeof(struct Channels));
|
||||
|
|
@ -6656,8 +6668,6 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
|
||||
if (boneIndex == -1) continue; // Animation channel for a node not in the skeleton
|
||||
|
||||
boneChannels[boneIndex].interpolationType = animData.channels[j].sampler->interpolation;
|
||||
|
||||
if (animData.channels[j].sampler->interpolation != cgltf_interpolation_type_max_enum)
|
||||
{
|
||||
if (channel.target_path == cgltf_animation_path_type_translation)
|
||||
|
|
@ -6691,7 +6701,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
animDuration = (time > animDuration)? time : animDuration;
|
||||
}
|
||||
|
||||
if (animData.name != NULL) strncpy(animations[a].name, animData.name, sizeof(animations[a].name) - 1);
|
||||
if (animData.name != NULL) snprintf(animations[a].name, sizeof(animations[a].name), "%s", animData.name);
|
||||
|
||||
animations[a].keyframeCount = (int)(animDuration*GLTF_FRAMERATE) + 1;
|
||||
animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *));
|
||||
|
|
@ -6701,7 +6711,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform));
|
||||
float time = (float)j / GLTF_FRAMERATE;
|
||||
|
||||
for (int k = 0; k < animations[a].boneCount; k++)
|
||||
for (unsigned int k = 0; k < animations[a].boneCount; k++)
|
||||
{
|
||||
Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]};
|
||||
Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]};
|
||||
|
|
@ -6709,7 +6719,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
|
||||
if (boneChannels[k].translate)
|
||||
{
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].translate->sampler->interpolation, boneChannels[k].translate->sampler->input, boneChannels[k].translate->sampler->output, time, &translation))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load translate pose data for bone %s", fileName, bones[k].name);
|
||||
}
|
||||
|
|
@ -6717,7 +6727,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
|
||||
if (boneChannels[k].rotate)
|
||||
{
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].rotate->sampler->input, boneChannels[k].rotate->sampler->output, time, &rotation))
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].rotate->sampler->interpolation, boneChannels[k].rotate->sampler->input, boneChannels[k].rotate->sampler->output, time, &rotation))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load rotate pose data for bone %s", fileName, bones[k].name);
|
||||
}
|
||||
|
|
@ -6725,7 +6735,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo
|
|||
|
||||
if (boneChannels[k].scale)
|
||||
{
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].interpolationType, boneChannels[k].scale->sampler->input, boneChannels[k].scale->sampler->output, time, &scale))
|
||||
if (!GetPoseAtTimeGLTF(boneChannels[k].scale->sampler->interpolation, boneChannels[k].scale->sampler->input, boneChannels[k].scale->sampler->output, time, &scale))
|
||||
{
|
||||
TRACELOG(LOG_INFO, "MODEL: [%s] Failed to load scale pose data for bone %s", fileName, bones[k].name);
|
||||
}
|
||||
|
|
@ -7177,7 +7187,7 @@ static Model LoadM3D(const char *fileName)
|
|||
for (i = 0; i < (int)m3d->numbone; i++)
|
||||
{
|
||||
model.skeleton.bones[i].parent = m3d->bone[i].parent;
|
||||
strncpy(model.skeleton.bones[i].name, m3d->bone[i].name, sizeof(model.skeleton.bones[i].name) - 1);
|
||||
snprintf(model.skeleton.bones[i].name, sizeof(model.skeleton.bones[i].name), "%s", m3d->bone[i].name);
|
||||
model.skeleton.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale;
|
||||
model.skeleton.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale;
|
||||
model.skeleton.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale;
|
||||
|
|
@ -7225,7 +7235,7 @@ static Model LoadM3D(const char *fileName)
|
|||
// Initialize runtime animation data: current pose and bone matrices
|
||||
model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform));
|
||||
model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix));
|
||||
for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity();
|
||||
}
|
||||
|
||||
m3d_free(m3d);
|
||||
|
|
@ -7235,7 +7245,7 @@ static Model LoadM3D(const char *fileName)
|
|||
return model;
|
||||
}
|
||||
|
||||
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
|
||||
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666 ms)
|
||||
|
||||
// Load M3D animation data
|
||||
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)
|
||||
|
|
@ -7279,14 +7289,14 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou
|
|||
|
||||
animations[a].keyframeCount = m3d->action[a].durationmsec/M3D_ANIMDELAY;
|
||||
animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *));
|
||||
strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name) - 1);
|
||||
snprintf(animations[a].name, sizeof(animations[a].name), "%s", m3d->action[a].name);
|
||||
|
||||
TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s | Frames: %d | Duration: %fs", fileName, animations[a].name, animations[a].keyframeCount, m3d->action[a].durationmsec);
|
||||
|
||||
for (i = 0; i < (int)m3d->numbone; i++)
|
||||
{
|
||||
bones[i].parent = m3d->bone[i].parent;
|
||||
strncpy(bones[i].name, m3d->bone[i].name, sizeof(bones[i].name) - 1);
|
||||
snprintf(bones[i].name, sizeof(bones[i].name), "%s", m3d->bone[i].name);
|
||||
}
|
||||
|
||||
// A special, never transformed "no bone" bone, used for boneless vertices
|
||||
|
|
|
|||
Loading…
Reference in a new issue