void Animation::createClips(Properties* animationProperties, unsigned int frameCount) { assert(animationProperties); Properties* pClip = animationProperties->getNextNamespace(); while (pClip != NULL && std::strcmp(pClip->getNamespace(), "clip") == 0) { int begin = pClip->getInt("begin"); int end = pClip->getInt("end"); AnimationClip* clip = createClip(pClip->getId(), ((float) begin / frameCount) * _duration, ((float) end / frameCount) * _duration); const char* repeat = pClip->getString("repeatCount"); if (repeat) { if (strcmp(repeat, ANIMATION_INDEFINITE_STR) == 0) { clip->setRepeatCount(AnimationClip::REPEAT_INDEFINITE); } else { float value; sscanf(repeat, "%f", &value); clip->setRepeatCount(value); } } const char* speed = pClip->getString("speed"); if (speed) { float value; sscanf(speed, "%f", &value); clip->setSpeed(value); } pClip = animationProperties->getNextNamespace(); } }
AnimationClip* AnimationClip::clone(Animation* animation) const { // Don't clone the elapsed time, listeners or crossfade information. AnimationClip* newClip = new AnimationClip(getId(), animation, getStartTime(), getEndTime()); newClip->setSpeed(getSpeed()); newClip->setRepeatCount(getRepeatCount()); newClip->setBlendWeight(getBlendWeight()); size_t size = _values.size(); newClip->_values.resize(size, NULL); for (size_t i = 0; i < size; ++i) { if (newClip->_values[i] == NULL) { newClip->_values[i] = new AnimationValue(*_values[i]); } else { *newClip->_values[i] = *_values[i]; } } return newClip; }
Animation::~Animation() { if (_defaultClip) { _defaultClip->stop(); SAFE_RELEASE(_defaultClip); } if (_clips) { std::vector<AnimationClip*>::iterator clipIter = _clips->begin(); while (clipIter != _clips->end()) { AnimationClip* clip = *clipIter; clip->stop(); SAFE_RELEASE(clip); clipIter++; } _clips->clear(); } SAFE_DELETE(_clips); }
/** * Keyboard callback */ void arrowPress(int key, int x, int y) { switch (key) { case GLUT_KEY_LEFT: aClip.decrementFrame(true); //camera.panLeft(1); break; case GLUT_KEY_RIGHT: aClip.incrementFrame(false); //camera.panRight(1); break; case GLUT_KEY_UP: if (++framesPerSecond > MAX_FRAMES) framesPerSecond = MAX_FRAMES; //camera.zoomIn(0.1f); break; case GLUT_KEY_DOWN: if (--framesPerSecond < MIN_FRAMES) framesPerSecond = MIN_FRAMES; //camera.zoomOut(0.1f); break; } glutPostRedisplay(); }
void AnimationController::update(float elapsedTime) { if (_state != RUNNING) return; Transform::suspendTransformChanged(); // Loop through running clips and call update() on them. std::list<AnimationClip*>::iterator clipIter = _runningClips.begin(); while (clipIter != _runningClips.end()) { AnimationClip* clip = (*clipIter); GP_ASSERT(clip); clip->addRef(); if (clip->isClipStateBitSet(AnimationClip::CLIP_IS_RESTARTED_BIT)) { // If the CLIP_IS_RESTARTED_BIT is set, we should end the clip and // move it from where it is in the running clips list to the back. clip->onEnd(); clip->setClipStateBit(AnimationClip::CLIP_IS_PLAYING_BIT); _runningClips.push_back(clip); clipIter = _runningClips.erase(clipIter); } else if (clip->update(elapsedTime)) { clip->release(); clipIter = _runningClips.erase(clipIter); } else { clipIter++; } clip->release(); } Transform::resumeTransformChanged(); if (_runningClips.empty()) _state = IDLE; }
/** * Callback used for menu events. */ void menuEvent(int id) { switch (id) { case MENU_NORMAL_MODE: printf("Entering normal mode...\n"); // robot->clearSelect(); break; case MENU_ZOOM_MODE: printf("Entering zoom mode...\n"); // robot->clearSelect(); break; case MENU_PAN_MODE: printf("Entering pan mode...\n"); // robot->clearSelect(); break; case MENU_LOAD_POSE: { printf("Loading pose from pose.dat...\n"); Keyframe k; SerialFile f("pose.dat", "rb"); k.readFromFile(f.getPointer()); f.close(); aClip.setFrameAt(aClip.getCurrentFrameIndex(), k); robot->getRobotFromKeyframe(&k); id = MENU_NORMAL_MODE; break; } case MENU_SAVE_POSE: { printf("Saving pose from pose.dat...\n"); Keyframe k; k.getKeyframeFromRobot(robot); SerialFile f("pose.dat", "wb"); k.writeToFile(f.getPointer()); f.close(); id = MENU_NORMAL_MODE; break; } case MENU_SAVE_ANIM: { SerialFile f("anim.dat", "wb"); aClip.writeToFile(f.getPointer()); f.close(); id = MENU_NORMAL_MODE; break; } case MENU_LOAD_ANIM: { SerialFile f("anim.dat", "rb"); aClip.readFromFile(f.getPointer()); f.close(); id = MENU_NORMAL_MODE; break; } case MENU_HEAD: printf("Entering head editing...\n"); // robot->setSelected("HEAD"); break; case MENU_NECK: printf("Entering neck editing...\n"); // robot->setSelected("NECK"); break; case MENU_UPPER_TORSO: printf("Entering upper torso editing...\n"); // robot->setSelected("UPPER_TORSO"); break; case MENU_LOWER_TORSO: printf("Entering lower torso editing...\n"); // robot->setSelected("LOWER_TORSO"); break; case MENU_PELVIS: printf("Entering pelvis editing...\n"); // robot->setSelected("PELVIS"); break; case MENU_LEFT_SHOULDER: printf("Entering left shoulder editing...\n"); // robot->setSelected("LEFT_SHOULDER"); break; case MENU_LEFT_UPPER_ARM: printf("Entering left upper arm editing...\n"); // robot->setSelected("LEFT_UPPER_ARM"); break; case MENU_LEFT_LOWER_ARM: printf("Entering left lower arm editing...\n"); // robot->setSelected("LEFT_LOWER_ARM"); break; case MENU_LEFT_HAND: printf("Entering left hand editing...\n"); // robot->setSelected("LEFT_HAND"); break; case MENU_RIGHT_SHOULDER: printf("Entering right shoulder editing...\n"); // robot->setSelected("RIGHT_SHOULDER"); break; case MENU_RIGHT_UPPER_ARM: printf("Entering right upper arm editing...\n"); // robot->setSelected("RIGHT_UPPER_ARM"); break; case MENU_RIGHT_LOWER_ARM: printf("Entering right lower arm editing...\n"); // robot->setSelected("RIGHT_LOWER_ARM"); break; case MENU_RIGHT_HAND: printf("Entering right hand editing...\n"); // robot->setSelected("RIGHT_HAND"); break; case MENU_LEFT_UPPER_LEG: printf("Entering left upper leg editing...\n"); // robot->setSelected("LEFT_UPPER_LEG"); break; case MENU_LEFT_LOWER_LEG: printf("Entering left lower leg editing...\n"); // robot->setSelected("LEFT_LOWER_LEG"); break; case MENU_LEFT_FOOT: printf("Entering left foot editing...\n"); // robot->setSelected("LEFT_FOOT"); break; case MENU_RIGHT_UPPER_LEG: printf("Entering right upper leg editing...\n"); // robot->setSelected("RIGHT_UPPER_LEG"); break; case MENU_RIGHT_LOWER_LEG: printf("Entering right lower leg editing...\n"); // robot->setSelected("RIGHT_LOWER_LEG"); break; case MENU_RIGHT_FOOT: printf("Entering right foot editing...\n"); // robot->setSelected("RIGHT_FOOT"); break; default: // Exit on unknown state printf("ERROR: Unknown menu state <%i>\n", id); return; } // Update the mode to reflect the changes currentMode = id; }
/** * Callback for mouse movement events. */ void mouseMoveEvent(int x, int y) { if (isPressed) { int changeInX = x - oldX; int changeInY = y - oldY; // If shift is being held, do something special if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) { if (changeInX > 0) { aClip.incrementFrame(false); } else if (changeInX < 0) { aClip.decrementFrame(true); } oldX = x; oldY = y; glutPostRedisplay(); return; } // Check to see what kind of event should take place switch (currentMode) { case MENU_NORMAL_MODE: camera.rotateRight(changeInX); camera.rotateUp(changeInY); break; case MENU_ZOOM_MODE: if (changeInY > 0) camera.zoomIn(0.01f); if (changeInY < 0) camera.zoomOut(0.01f); break; case MENU_PAN_MODE: camera.panRight(changeInX); break; case MENU_HEAD: robot->setAngle("HEAD", robot->getAngleH("HEAD") + changeInY, robot->getAngleV("HEAD") + changeInX); break; case MENU_NECK: robot->setAngle("NECK", robot->getAngleH("NECK") + changeInY, robot->getAngleV("NECK") + changeInX); break; case MENU_UPPER_TORSO: robot->setAngle("UPPER_TORSO", robot->getAngleH("UPPER_TORSO") + changeInY, robot->getAngleV("UPPER_TORSO") + changeInX); break; case MENU_LOWER_TORSO: robot->setAngle("LOWER_TORSO", robot->getAngleH("LOWER_TORSO") + changeInY, robot->getAngleV("LOWER_TORSO") + changeInX); break; case MENU_PELVIS: robot->setAngle("PELVIS", robot->getAngleH("PELVIS") + changeInY, robot->getAngleV("PELVIS") + changeInX); break; case MENU_LEFT_SHOULDER: robot->setAngle("LEFT_SHOULDER", robot->getAngleH("LEFT_SHOULDER") + changeInY, robot->getAngleV("LEFT_SHOULDER") + changeInX); break; case MENU_LEFT_UPPER_ARM: robot->setAngle("LEFT_UPPER_ARM", robot->getAngleH("LEFT_UPPER_ARM") + changeInY, robot->getAngleV("LEFT_UPPER_ARM") + changeInX); break; case MENU_LEFT_LOWER_ARM: robot->setAngle("LEFT_LOWER_ARM", robot->getAngleH("LEFT_LOWER_ARM") + changeInY, robot->getAngleV("LEFT_LOWER_ARM") + changeInX); break; case MENU_LEFT_HAND: robot->setAngle("LEFT_HAND", robot->getAngleH("LEFT_HAND") + changeInY, robot->getAngleV("LEFT_HAND") + changeInX); break; case MENU_RIGHT_SHOULDER: robot->setAngle("RIGHT_SHOULDER", robot->getAngleH("RIGHT_SHOULDER") + changeInY, robot->getAngleV("RIGHT_SHOULDER") + changeInX); break; case MENU_RIGHT_UPPER_ARM: robot->setAngle("RIGHT_UPPER_ARM", robot->getAngleH("RIGHT_UPPER_ARM") + changeInY, robot->getAngleV("RIGHT_UPPER_ARM") + changeInX); break; case MENU_RIGHT_LOWER_ARM: robot->setAngle("RIGHT_LOWER_ARM", robot->getAngleH("RIGHT_LOWER_ARM") + changeInY, robot->getAngleV("RIGHT_LOWER_ARM") + changeInX); break; case MENU_RIGHT_HAND: robot->setAngle("RIGHT_HAND", robot->getAngleH("RIGHT_HAND") + changeInY, robot->getAngleV("RIGHT_HAND") + changeInX); break; case MENU_LEFT_UPPER_LEG: robot->setAngle("LEFT_UPPER_LEG", robot->getAngleH("LEFT_UPPER_LEG") + changeInY, robot->getAngleV("LEFT_UPPER_LEG") + changeInX); break; case MENU_LEFT_LOWER_LEG: robot->setAngle("LEFT_LOWER_LEG", robot->getAngleH("LEFT_LOWER_LEG") + changeInY, robot->getAngleV("LEFT_LOWER_LEG") + changeInX); break; case MENU_LEFT_FOOT: robot->setAngle("LEFT_FOOT", robot->getAngleH("LEFT_FOOT") + changeInY, robot->getAngleV("LEFT_FOOT") + changeInX); break; case MENU_RIGHT_UPPER_LEG: robot->setAngle("RIGHT_UPPER_LEG", robot->getAngleH("RIGHT_UPPER_LEG") + changeInY, robot->getAngleV("RIGHT_UPPER_LEG") + changeInX); break; case MENU_RIGHT_LOWER_LEG: robot->setAngle("RIGHT_LOWER_LEG", robot->getAngleH("RIGHT_LOWER_LEG") + changeInY, robot->getAngleV("RIGHT_LOWER_LEG") + changeInX); break; case MENU_RIGHT_FOOT: robot->setAngle("RIGHT_FOOT", robot->getAngleH("RIGHT_FOOT") + changeInY, robot->getAngleV("RIGHT_FOOT") + changeInX); break; default: // Exit on unknown state printf("ERROR: Unknown menu state <%i> in motion!\n", currentMode); return; } Keyframe k_; k_.getKeyframeFromRobot(robot); aClip.setFrameAt(aClip.getCurrentFrameIndex(), k_); oldX = x; oldY = y; glutPostRedisplay(); } }
/** * Renders the graphics onto the screen. * Uses: * GL_QUADS * glColor */ void render(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0f, 640.0f/640.0f, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Background color is black */ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Update camera */ camera.update(); /* Render the robot */ Keyframe k_ = aClip.getCurrentFrame(); robot->getRobotFromKeyframe(&k_); robot->render(); /* Draw the text */ glLoadIdentity(); std::string msg; char frame[4]; // The current frame sprintf(frame, "%d", aClip.getCurrentFrameIndex()); msg = "Current Frame: "; msg += frame; Text::drawBitmapString(-0.9f, 0.9f, GLUT_BITMAP_8_BY_13, msg); // The current keyframe sprintf(frame, "%d", aClip.getKeyframeIndex()); msg = "Keyframe: "; if (aClip.isKeyframeAtCurrent()) msg += frame; Text::drawBitmapString(-0.9f, 0.85f, GLUT_BITMAP_8_BY_13, msg); // Actual frames per second sprintf(frame, "%d", framesTotal); msg = "Frames Per Second: "; if (isPlaying) msg += frame; Text::drawBitmapString(-0.9f, 0.80f, GLUT_BITMAP_8_BY_13, msg); // The requested FPS sprintf(frame, "%d", framesPerSecond); msg = "Requested FPS: "; msg += frame; Text::drawBitmapString(-0.9f, -0.9f, GLUT_BITMAP_8_BY_13, msg); // Playing status if (isPlaying) { if (playingForward) msg = "Forward"; if (playingBackward) msg = "Backward"; } else { msg = "Stopped"; } Text::drawBitmapString(0.8f, -0.9f, GLUT_BITMAP_8_BY_13, msg); /* Swap the buffers to display changes */ glutSwapBuffers(); }
/* * Written by Robert "Chip" Senkbeil * Uses -lglut, -lGLU, and -lGL to compile on Linux. */ int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition(0, 0); glutInitWindowSize(640, 640); glutCreateWindow(argv[0]); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); //glutReshapeFunc(/* ... */); glutSpecialFunc(arrowPress); glutKeyboardFunc(keyPress); glutMouseFunc(mouseEvent); glutMotionFunc(mouseMoveEvent); glutDisplayFunc(render); glutIdleFunc(idleEvent); // Build and attach the menu buildPopupMenu(); glutAttachMenu(GLUT_RIGHT_BUTTON); // Allocate memory for a new robot printf("Allocating new robot...\n"); robot = new Robot(); // Add robot initial keyframe to animation clip { Keyframe k_; k_.getKeyframeFromRobot(robot); aClip.addKeyframeAtCurrent(k_); } printf("Setting up the camera...\n"); camera.setCameraMaxDistance(4.0f); //camera.lock(); // Set default fps framesPerSecond = DEFAULT_FRAMES_PER_SECOND; isPlaying = 0; playingForward = 1; playingBackward = 0; currentTime = 0; baseTime = 0; frames = 0; framesTotal = 0; // Set termination callback atexit(terminate_prog); // Enable lighting setupLight(); // Setup a global material initMaterial(); // Enable texture glEnable(GL_TEXTURE_2D); robot->loadTexture("texture/CorrugatedSharp.png"); // Start the main loop glutMainLoop(); // Exit program return 0; }