/* MotionManager::startMotion start a motion */ bool MotionManager::startMotion(VMD * vmd, const char *name, bool full, bool once, bool enableSmooth, bool enableRePos, float priority) { MotionPlayer *m, *tmp1, *tmp2; if (vmd == NULL || name == NULL) return false; /* purge inactive motion managers */ purgeMotion(); /* allocate new motion */ m = new MotionPlayer; MotionPlayer_initialize(m); m->name = MMDFiles_strdup(name); m->priority = priority; m->onEnd = once ? 2 : 1; /* if loop is not specified, this motion will be deleted */ m->ignoreStatic = full ? false : true; m->enableSmooth = enableSmooth; m->enableRePos = enableRePos; startMotionSub(vmd, m); /* set reset timer for bones/faces that are not controlled by the given base motion */ if (!m->ignoreStatic) m_beginningNonControlledBlend = 10.0f; /* add this new motion to the last of the motion player list, consulting priority */ if (m_playerList == NULL || m_playerList->priority > m->priority) { m->next = m_playerList; m_playerList = m; } else { tmp2 = m_playerList->next; /* skip the base motion */ tmp1 = m_playerList; while (tmp2) { if (tmp2->priority > m->priority) { /* insert here */ m->next = tmp2; tmp1->next = m; break; } tmp1 = tmp2; tmp2 = tmp2->next; } if (!tmp2) { /* append */ m->next = NULL; tmp1->next = m; } } return true; }
/* PMDFace::setup: initialize and setup face */ void PMDFace::setup(PMDFile_Face *face, PMDFile_Face_Vertex *faceVertexList) { unsigned long i; char name[21]; clear(); /* name */ strncpy(name, face->name, 20); name[20] = '\0'; m_name = MMDFiles_strdup(name); /* type */ m_type = face->type; /* number of vertices */ m_numVertex = face->numVertex; if (m_numVertex) { /* vertex list */ m_vertex = (PMDFaceVertex *) malloc(sizeof(PMDFaceVertex) * m_numVertex); for (i = 0; i < m_numVertex; i++) { m_vertex[i].id = faceVertexList[i].vertexID; if (m_vertex[i].id >= PMDFACE_MAXVERTEXID) /* a workaround for some models with corrupted face index values */ m_vertex[i].id -= PMDFACE_MAXVERTEXID; m_vertex[i].pos.setValue(faceVertexList[i].pos[0], faceVertexList[i].pos[1], faceVertexList[i].pos[2]); } } #ifdef MMDFILES_CONVERTCOORDINATESYSTEM /* left-handed system: PMD, DirectX */ /* right-handed system: OpenGL, bulletphysics */ /* reverse Z value on vertices */ for (i = 0; i < m_numVertex; i++) { m_vertex[i].pos.setZ(- m_vertex[i].pos.z()); } #endif /* MMDFILES_CONVERTCOORDINATESYSTEM */ }
/* MMDFiles_basename: get file name from path */ char *MMDFiles_basename(const char *file) { int i, len, index = -1; char size; char *base; len = MMDFiles_strlen(file); for(i = 0; i < len; i += size) { size = MMDFiles_getcharsize(&file[i]); if(size == 1 && MMDFiles_dirseparator(file[i]) == true) index = i; } if(index >= 0) { base = (char *) malloc(sizeof(char) * (len - index)); strncpy(base, &file[index + 1], len - index - 1); base[len - index - 1] = '\0'; } else { base = MMDFiles_strdup(file); } return base; }
/* MMDFiles_dirname: get directory name from path */ char *MMDFiles_dirname(const char *file) { int i, len, index = -1; char size; char *dir; len = MMDFiles_strlen(file); for(i = 0; i < len; i += size) { size = MMDFiles_getcharsize(&file[i]); if(size == 1 && MMDFiles_dirseparator(file[i]) == true) index = i; } if(index >= 0) { dir = (char *) malloc(sizeof(char *) * (index + 1)); strncpy(dir, file, index); dir[index] = '\0'; } else { dir = MMDFiles_strdup("."); } return dir; }
/* MMDAgent_strdup: strdup */ char *MMDAgent_strdup(const char *str) { return MMDFiles_strdup(str); }
/* PMDBone::setup: initialize and setup bone */ bool PMDBone::setup(PMDFile_Bone *b, PMDBone *boneList, unsigned short maxBones, PMDBone *rootBone) { bool ret = true; char name[21]; clear(); /* name */ strncpy(name, b->name, 20); name[20] = '\0'; m_name = MMDFiles_strdup(name); /* mark if this bone should be treated as angle-constrained bone in IK process */ if (strstr(m_name, PMDBONE_KNEENAME)) m_limitAngleX = true; else m_limitAngleX = false; /* parent bone */ if (b->parentBoneID != -1) { /* has parent bone */ if (b->parentBoneID >= maxBones) { ret = false; } else { m_parentBone = &(boneList[b->parentBoneID]); m_parentIsRoot = false; } } else { /* no parent bone */ if (rootBone) { /* set model root bone as parent */ m_parentBone = rootBone; m_parentIsRoot = true; } else { /* no parent, just use it */ m_parentIsRoot = false; } } /* child bone */ if (b->childBoneID != -1) { if (b->childBoneID >= maxBones) ret = false; else m_childBone = &(boneList[b->childBoneID]); } /* type */ m_type = b->type; /* target bone to which this bone is subject to */ if (m_type == UNDER_IK || m_type == UNDER_ROTATE) { m_targetBone = &(boneList[b->targetBoneID]); if (b->targetBoneID >= maxBones) ret = false; else m_targetBone = &(boneList[b->targetBoneID]); } /* store the value of targetBoneID as co-rotate coef if kind == FOLLOW_ROTATE */ if (m_type == FOLLOW_ROTATE) m_rotateCoef = (float) b->targetBoneID * 0.01f; /* store absolute bone positions */ /* reverse Z value on bone position */ #ifdef MMDFILES_CONVERTCOORDINATESYSTEM m_originPosition = btVector3(b->pos[0], b->pos[1], -b->pos[2]); #else m_originPosition = btVector3(b->pos[0], b->pos[1], b->pos[2]); #endif /* MMDFILES_CONVERTCOORDINATESYSTEM */ /* reset current transform values */ m_trans.setOrigin(m_originPosition); /* set absolute position->origin transform matrix for skinning */ m_transMoveToOrigin.setOrigin(-m_originPosition); return ret; }
/* MMDFiles_pathdup: convert charset from application to system */ char *MMDFiles_pathdup(const char *str) { #ifdef _WIN32 return MMDFiles_strdup(str); #endif /* _WIN32 */ #ifdef __APPLE__ size_t i, size; char *inBuff, *outBuff; size_t inLen, outLen; CFStringRef cfs; inLen = MMDFiles_strlen(str); if(inLen <= 0) return NULL; inBuff = MMDFiles_strdup(str); if(inBuff == NULL) return NULL; /* convert directory separator */ for(i = 0; i < inLen; i += size) { size = MMDFiles_getcharsize(&inBuff[i]); if(size == 1 && MMDFiles_dirseparator(inBuff[i]) == true) inBuff[i] = MMDFILES_DIRSEPARATOR; } /* convert multi-byte char */ cfs = CFStringCreateWithCString(NULL, inBuff, kCFStringEncodingDOSJapanese); outLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfs), kCFStringEncodingUTF8) + 1; outBuff = (char *) malloc(outLen); CFStringGetCString(cfs, outBuff, outLen, kCFStringEncodingUTF8); CFRelease(cfs); free(inBuff); return outBuff; #endif /* __APPLE__ */ #if !defined(_WIN32) && !defined(__APPLE__) iconv_t ic; size_t i, size; char *inBuff, *outBuff; char *inFile, *outFile; size_t inLen, outLen; inLen = MMDFiles_strlen(str); if(inLen <= 0) return NULL; outLen = inLen * MMDFILESUTILS_MAXCHARBYTE; ic = iconv_open(MMDFILES_CHARSET, "SJIS"); if(ic < 0) return NULL; inBuff = inFile = MMDFiles_strdup(str); outBuff = outFile = (char *) calloc(outLen, sizeof(char)); /* convert directory separator */ for(i = 0; i < inLen; i += size) { size = MMDFiles_getcharsize(&inFile[i]); if(size == 1 && MMDFiles_dirseparator(inFile[i]) == true) inFile[i] = MMDFILES_DIRSEPARATOR; } /* convert muli-byte char */ if(iconv(ic, &inFile, &inLen, &outFile, &outLen) >= 0) { outFile = '\0'; } else { strcpy(outBuff, ""); } iconv_close(ic); free(inBuff); return outBuff; #endif /* !_WIN32 && !__APPLE__ */ }