/* Variables::set: set value */ void Variables::set(const char *alias, const char *str1, const char *str2) { Value *val; float max, min, tmp; if(MMDAgent_strlen(alias) <= 0) return; /* check the same alias */ for(val = m_head; val; val = val->next) { if(MMDAgent_strequal(val->name, alias)) break; } /* push */ if(val == NULL) { val = (Value *) malloc(sizeof(Value)); val->name = MMDAgent_strdup(alias); val->next = NULL; if(m_tail == NULL) { m_head = val; val->prev = NULL; } else { m_tail->next = val; val->prev = m_tail; } m_tail = val; } else { free(val->sval); } /* set string */ if(str2 == NULL) { val->sval = MMDAgent_strdup(str1); } else { val->sval = (char *) malloc(sizeof(char) * (MMDAgent_strlen(str1) + 1 + MMDAgent_strlen(str2) + 1)); sprintf(val->sval, "%s|%s", str1, str2); } /* set float */ if(str2 == NULL) { val->fval = MMDAgent_str2float(str1); } else { min = MMDAgent_str2float(str1); max = MMDAgent_str2float(str2); if(max < min) { tmp = max; max = min; min = tmp; } val->fval = min + (max - min) * (rand() - 0.0f) * (1.0f / (RAND_MAX - 0.0f)); /* 0.0f is RAND_MIN */ } m_mmdagent->sendEventMessage(VARIABLES_VALUESETEVENT, alias); /* send message */ }
/* Variables::evaluate: evaluate value */ void Variables::evaluate(const char *alias, const char *mode, const char *str) { Value *val; float f1, f2; bool ret; /* get value 1 */ for(val = m_head; val; val = val->next) { if(MMDAgent_strequal(val->name, alias) == true) { f1 = val->fval; break; } } if(val == NULL) return; /* get value 2 */ f2 = MMDAgent_str2float(str); /* evaluate */ if(MMDAgent_strequal(mode, VARIABLES_EQ) == true) { if(f1 == f2) ret = true; else ret = false; } else if(MMDAgent_strequal(mode, VARIABLES_NE) == true) { if(f1 != f2) ret = true; else ret = false; } else if(MMDAgent_strequal(mode, VARIABLES_LE) == true) { if(f1 <= f2) ret = true; else ret = false; } else if(MMDAgent_strequal(mode, VARIABLES_LT) == true) { if(f1 < f2) ret = true; else ret = false; } else if(MMDAgent_strequal(mode, VARIABLES_GE) == true) { if(f1 >= f2) ret = true; else ret = false; } else if(MMDAgent_strequal(mode, VARIABLES_GT) == true) { if(f1 > f2) ret = true; else ret = false; } else { /* unknown mode */ return; } if(ret == true) m_mmdagent->sendEventMessage(VARIABLES_VALUEEVALEVENT, "%s|%s|%s|%s", alias, mode, str, VARIABLES_TRUE); else m_mmdagent->sendEventMessage(VARIABLES_VALUEEVALEVENT, "%s|%s|%s|%s", alias, mode, str, VARIABLES_FALSE); }
/* LipSync::load: initialize and load lip setting */ bool LipSync::load(const char *file) { int i, j; FILE *fp; int len; char buff[LIPSYNC_MAXBUFLEN]; bool err = false; fp = MMDAgent_fopen(file, "r"); if(fp == NULL) return false; /* number of expression */ len = MMDAgent_fgettoken(fp, buff); if(len <= 0) { fclose(fp); return false; } m_numMotion = MMDAgent_str2int(buff); if(m_numMotion <= 0) { fclose(fp); clear(); return false; } /* motion name */ m_motion = (char **) malloc(sizeof(char *) * m_numMotion); for(i = 0; i < m_numMotion; i++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_motion[i] = MMDAgent_strdup(buff); } if(err == true) { fclose(fp); clear(); return false; } /* number of phone */ len = MMDAgent_fgettoken(fp, buff); if(len <= 0) { fclose(fp); clear(); return false; } m_numPhone = MMDAgent_str2int(buff); if(m_numPhone <= 0) { fclose(fp); clear(); return false; } /* phone name, type, and blend rate */ m_phone = (char **) malloc(sizeof(char *) * m_numPhone); m_blendRate = (float **) malloc(sizeof(float *) * m_numPhone); for(i = 0; i < m_numPhone; i++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_phone[i] = MMDAgent_strdup(buff); m_blendRate[i] = (float *) malloc(sizeof(float) * m_numMotion); for(j = 0; j < m_numMotion; j++) { len = MMDAgent_fgettoken(fp, buff); if(len <= 0) err = true; m_blendRate[i][j] = MMDAgent_str2float(buff); if(m_blendRate[i][j] < 0.0f) err = true; } } if(err == true) { fclose(fp); clear(); return false; } fclose(fp); return true; }
/* LipSync::createMotion: create motion from phoneme sequence */ bool LipSync::createMotion(const char *str, unsigned char **rawData, unsigned long *rawSize) { int i, j, k; int len; char *buf, *p, *save; LipKeyFrame *head, *tail, *tmp1, *tmp2; float f, diff; int totalNumKey; unsigned long currentFrame; unsigned char *data; VMDFile_Header *header; unsigned long *numBoneKeyFrames; unsigned long *numFaceKeyFrames; VMDFile_FaceFrame *face; /* check */ if(str == NULL || m_numMotion <= 0 || m_numPhone <= 0) return false; /* initialize */ (*rawData) = NULL; (*rawSize) = 0; /* get phone index and duration */ buf = MMDAgent_strdup(str); head = NULL; tail = NULL; diff = 0.0f; for(i = 0, k = 0, p = MMDAgent_strtok(buf, LIPSYNC_SEPARATOR, &save); p; i++, p = MMDAgent_strtok(NULL, LIPSYNC_SEPARATOR, &save)) { if(i % 2 == 0) { for(j = 0; j < m_numPhone; j++) { if(MMDAgent_strequal(m_phone[j], p)) { k = j; break; } } if(m_numPhone <= j) k = 0; } else { tmp1 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp1->phone = k; f = 0.03f * MMDAgent_str2float(p) + diff; /* convert ms to frame */ tmp1->duration = (int) (f + 0.5); if(tmp1->duration < 1) tmp1->duration = 1; diff = f - tmp1->duration; tmp1->rate = 1.0f; tmp1->next = NULL; if(head == NULL) head = tmp1; else tail->next = tmp1; tail = tmp1; } } /* add final closed lip */ tmp1 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp1->phone = 0; tmp1->duration = 1; tmp1->rate = 0.0f; tmp1->next = NULL; if(head == NULL) head = tmp1; else tail->next = tmp1; tail = tmp1; /* insert interpolation lip motion */ for(tmp1 = head; tmp1; tmp1 = tmp1->next) { if(tmp1->next && tmp1->duration > LIPSYNC_INTERPOLATIONMARGIN) { tmp2 = (LipKeyFrame *) malloc(sizeof(LipKeyFrame)); tmp2->phone = tmp1->phone; tmp2->duration = LIPSYNC_INTERPOLATIONMARGIN; tmp2->rate = tmp1->rate * LIPSYNC_INTERPOLATIONRATE; tmp2->next = tmp1->next; tmp1->duration -= LIPSYNC_INTERPOLATIONMARGIN; tmp1->next = tmp2; tmp2 = tmp1; } } /* count length of key frame */ len = 0; for(tmp1 = head; tmp1; tmp1 = tmp1->next) len++; totalNumKey = m_numMotion * len; /* create memories */ (*rawSize) = sizeof(VMDFile_Header) + sizeof(unsigned long) + sizeof(unsigned long) + sizeof(VMDFile_FaceFrame) * totalNumKey; i = (*rawSize); i = sizeof(unsigned char) * (*rawSize); (*rawData) = (unsigned char *) malloc(i); data = (*rawData); /* header */ header = (VMDFile_Header *) data; strncpy(header->header, "Vocaloid Motion Data 0002", 30); data += sizeof(VMDFile_Header); /* number of key frame for bone */ numBoneKeyFrames = (unsigned long *) data; (*numBoneKeyFrames) = 0; data += sizeof(unsigned long); /* number of key frame for expression */ numFaceKeyFrames = (unsigned long *) data; (*numFaceKeyFrames) = totalNumKey; data += sizeof(unsigned long); /* set key frame */ for (i = 0; i < m_numMotion; i++) { currentFrame = 0; for(tmp1 = head; tmp1; tmp1 = tmp1->next) { face = (VMDFile_FaceFrame *) data; strncpy(face->name, m_motion[i], 15); face->keyFrame = currentFrame; face->weight = m_blendRate[tmp1->phone][i] * tmp1->rate; data += sizeof(VMDFile_FaceFrame); currentFrame += tmp1->duration; } } /* free */ free(buf); for(tmp1 = head; tmp1; tmp1 = tmp2) { tmp2 = tmp1->next; free(tmp1); } return true; }
/* Option::load: load options from config file */ bool Option::load(const char *file) { FILE *fp; char buf[OPTION_MAXBUFLEN]; int len; char *p1; int ivec2[2]; float fvec3[3]; float fvec4[4]; fp = MMDAgent_fopen(file, "r"); if (fp == NULL) return false; while (fgets(buf, OPTION_MAXBUFLEN, fp)) { len = MMDAgent_strlen(buf); if(len <= 0) continue; p1 = &(buf[len - 1]); while (p1 >= &(buf[0]) && (*p1 == '\n' || *p1 == '\r' || *p1 == '\t' || *p1 == ' ')) { *p1 = L'\0'; p1--; } p1 = &(buf[0]); if (*p1 == '#') continue; while (*p1 != L'=' && *p1 != L'\0') p1++; if (*p1 == L'\0') continue; *p1 = L'\0'; p1++; /* overwrite option values */ if(MMDAgent_strequal(buf, OPTION_USECARTOONRENDERING_STR)) { setUseCartoonRendering(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_USEMMDLIKECARTOON_STR)) { setUseMMDLikeCartoon(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_CARTOONEDGEWIDTH_STR)) { setCartoonEdgeWidth(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_CARTOONEDGESTEP_STR)) { setCartoonEdgeStep(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_CARTOONEDGESELECTEDCOLOR_STR)) { if(MMDAgent_str2fvec(p1, fvec4, 4)) setCartoonEdgeSelectedColor(fvec4); } else if(MMDAgent_strequal(buf, OPTION_CAMERAROTATION_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setCameraRotation(fvec3); } else if(MMDAgent_strequal(buf, OPTION_CAMERATRANSITION_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setCameraTransition(fvec3); } else if(MMDAgent_strequal(buf, OPTION_CAMERADISTANCE_STR)) { setCameraDistance(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_CAMERAFOVY_STR)) { setCameraFovy(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_STAGESIZE_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setStageSize(fvec3); } else if(MMDAgent_strequal(buf, OPTION_SHOWFPS_STR)) { setShowFps(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_FPSPOSITION_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setFpsPosition(fvec3); } else if(MMDAgent_strequal(buf, OPTION_WINDOWSIZE_STR)) { if(MMDAgent_str2ivec(p1, ivec2, 2)) setWindowSize(ivec2); } else if(MMDAgent_strequal(buf, OPTION_FULLSCREEN_STR)) { setFullScreen(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_LOGSIZE_STR)) { if(MMDAgent_str2ivec(p1, ivec2, 2)) setLogSize(ivec2); } else if(MMDAgent_strequal(buf, OPTION_LOGPOSITION_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setLogPosition(fvec3); } else if(MMDAgent_strequal(buf, OPTION_LOGSCALE_STR)) { setLogScale(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_LIGHTDIRECTION_STR)) { if(MMDAgent_str2fvec(p1, fvec4, 4)) setLightDirection(fvec4); } else if(MMDAgent_strequal(buf, OPTION_LIGHTINTENSITY_STR)) { setLightIntensity(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_LIGHTCOLOR_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setLightColor(fvec3); } else if(MMDAgent_strequal(buf, OPTION_CAMPUSCOLOR_STR)) { if(MMDAgent_str2fvec(p1, fvec3, 3)) setCampusColor(fvec3); } else if(MMDAgent_strequal(buf, OPTION_MAXMULTISAMPLING_STR)) { setMaxMultiSampling(MMDAgent_str2int(p1)); } else if(MMDAgent_strequal(buf, OPTION_MOTIONADJUSTTIME_STR)) { setMotionAdjustTime(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_LIPSYNCPRIORITY_STR)) { setLipsyncPriority(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_BULLETFPS_STR)) { setBulletFps(MMDAgent_str2int(p1)); } else if(MMDAgent_strequal(buf, OPTION_GRAVITYFACTOR_STR)) { setGravityFactor(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_ROTATESTEP_STR)) { setRotateStep(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_TRANSLATESTEP_STR)) { setTranslateStep(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_DISTANCESTEP_STR)) { setDistanceStep(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_FOVYSTEP_STR)) { setFovyStep(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_USESHADOWMAPPING_STR)) { setUseShadowMapping(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_SHADOWMAPPINGTEXTURESIZE_STR)) { setShadowMappingTextureSize(MMDAgent_str2int(p1)); } else if(MMDAgent_strequal(buf, OPTION_SHADOWMAPPINGSELFDENSITY_STR)) { setShadowMappingSelfDensity(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_SHADOWMAPPINGFLOORDENSITY_STR)) { setShadowMappingFloorDensity(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_SHADOWMAPPINGLIGHTFIRST_STR)) { setShadowMappingLightFirst(MMDAgent_str2bool(p1)); } else if(MMDAgent_strequal(buf, OPTION_DISPLAYCOMMENTTIME_STR)) { setDisplayCommentTime(MMDAgent_str2float(p1)); } else if(MMDAgent_strequal(buf, OPTION_MAXNUMMODEL_STR)) { setMaxNumModel(MMDAgent_str2int(p1)); } } fclose(fp); return true; }