The is an optional assignment that will be worth up to 5 bonus points. Participation will count towards your participation grade. During our last lab, we will have a contest for best project in each lab session. The goal of this bonus is to challenge yourself to implement a concept of class that you find interesting but did not address in the assignments. As you only have a week to focus on this, think of it more as a Choose your own assignment rather than a project. Also, get something working first and then make it 'fancy' and unique.
You may choose to work in pairs or individually.
The page will be updated with resources to help you accomplish this free-form assignment. Please don't be shy about asking for more information.
Over the next few weeks, I will add basecode and tips to guide you in implementing one of these ideas. I'm also open to your ideas for a demo, but discuss it with me first. To prevent grading from being overly subjective, I've attached points to each idea based on the difficulty of the task. Mix and match ideas to gain multiple points.
Splicing. (1 point) Create new motions by blending motions for
parts of the body. For example, in your blend assignment you blended the rotations
for every joint. To splice part the upper body, you would only blend the upper body
joints.
This task requires
Use your blend assignment as a starting point.
Infinite walker. (2 points) Implement a character which can walk
forward forever. The most straightforward approach is to implement a state machine which
crossfades the walking motion to itself whenever the character is about to complete
the motion.
Use your blend assignment as a starting point.
Motion controller. (4 points) Create a character that can walk and stand based on user keyboard control. This task extends the infinite walker so it can either stand or walk based on keyboard input.
This task requires
Use your blend assignment as a starting point.
Dance party. (2 points) Implement a character which can dance forever. The most straightforward approach is to implement a state machine which crossfades to itself whenever the character is about to complete the motion. To create variations on the dance, crossfade between randomized frames.
Use your blend assignment as a starting point.
Animated platform. (1 point)Define a 3D spline in the environment. Use the FKViewer as a starting point (esp. if you want to move a character around as an add-on feature). This task requires
// get the position for the platform vec3 ppos = mSpline.getValue(mCurrentTime); // set the color GLfloat c[4] = {1.0, 1.0, 1.0, 1.0}; // set RGBA color glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); // set the position and scale and draw a box glPushMatrix(); glTranslatef(ppos[0], ppos[1], ppos[2]); glScalef(100, 10, 100); // box dimensions are (100,10,100) glutSolidCube(1.0); glPopMatrix();
Character on a moving platform. (1 point)After implementing a moving platform, position a character on it. As the platform moves, so should the character. To complete this task, update the character so it's root is positioned relative to the platform.
Tentacle. (1 point)Define a kinematic chain with N joints (N > 2). The basecode IKSimple.cpp gives an example of how to do this. Undulating movement can be modeled with sine curves. For example, suppose we rotate each joint around its local Z axis between some thetaMin and thetaMax. Each time step, we update the rotation angle
fraction = (sin(mCurrentTime) * 0.5) + 0.5 // transform range to [0,1] from [-1,1] theta = fraction*(thetaMax - thetaMin) + thetaMin // transform range to [thetaMin, thetaMax]To improve the motion, each child can sample sine differently, for example, with an offset
fraction = (sin(mCurrentTime + offset*jointID) * 0.5) + 0.5 theta = fraction*(thetaMax - thetaMin) + thetaMin
Use IKSimple.cpp as a starting point.
Flying creature. (2 point)Design a character with flapping wings. The skeleton should have a root joint with child jointt representing each wing. The basecode IKSimple.cpp gives an example of how to define a skeleton. Each frame, update the wings to flap.
Use IKSimple.cpp as a starting point.
Flying creature on a trajectory. (1 point)After implementing the flying creature, define a spline in the scene. Then, update the position of the root based on the spline.
Gaze controller. (1 points) Based on the position of the mouse, animate the head of the character to follow the target. To complete this task
For best results, use your forward kinematics assignment as a starting point. The gaze will look best if combined with a natural motion.
Use this modified character drawer which draws eyes so you can see the gaze more easily (GooglyEyes.h, GooglyEyes.cpp)
Reaching. (2 points) Implement a character that smoothly reaches toward a target (rather than snaps to it as in the IK assignment). To complete this task
Use the IKViewer as a starting point.
Foot clamping. (2 points) Dynamically modify the position of the feet based on the height of the terrain. To complete this task
To get you started, I created a version of the forward kinematics assignment which contains an uneven floor. (FloorMain.cpp, FloorViewer.h, FloorViewer.cpp)
Custom character. (up to 2 points, depending on effort)Create a unique character. The basecode includes a drawing class which takes an AnimatbleHierarchy and recursively goes through each joint to draw it. By modifying this process you can create different looking characters. The most straight-forward approach is to copy this code and modify it. Then in draw(), you use your drawer instead of the default. Here are some simple things to try
Change the background color. (0.1 points)You can change the background color. Modify the following line in ABasicViewer::initializeOpenGL()
glClearColor(0.8, 0.8, 0.8, 1.0); // R,G,B,A
Create multiple characters and/or animated objects. (1 point) This is a good point to grab once you get one of the previous bonus working. For example, if you animated one character walking forward infinitely, now you can create 10 characters walking forward. Characters can be drawn an arbitrary number of times in draw3DViewer(). In the code below, we draw two characters next to each other along the X axis using the function glTranslate().
void BVHViewer::draw3DView() { glViewport(0, 0, (GLsizei)mWindowWidth, (GLsizei)mWindowHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); // Draw the front face only, except for the texts and lights. glEnable(GL_LIGHTING); // Set the view to the current camera settings. mCamera.draw(); GLfloat pos[4]; pos[0] = mCamera.getPosition()[0]; pos[1] = mCamera.getPosition()[1]; pos[2] = mCamera.getPosition()[2]; pos[3] = 1.0; glLightfv(GL_LIGHT0, GL_POSITION, pos); // draw two characters glPushMatrix(); glTranslatef(-200, 0, 0); mDrawer.draw(mBVHController.getSkeleton()); glPopMatrix(); glPushMatrix(); glTranslatef(200, 0, 0); mDrawer.draw(mBVHController.getSkeleton()); glPopMatrix(); glDisable(GL_LIGHTING); displayGrid(); }For full points, this bonus should either be
For this assignment, you may extend an existing homework or create a new application. In either case, the structure of the basecode applications are all similar. Each is based on a viewer class defined in libui.so (source is in libsrc/ui/aBasicViewer.h) which defines functions for drawing, updating, receiving mouse and keyboard input, and managing UI widgets.
To draw objects in the 3D view, override ABasicViewer::draw3DView(). For example. the following example draws a cube at the origin.
void MyBasicViewer::draw3DView() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); // Set the view to the current camera settings. mCamera.draw(); // Your custom code here glutSolidCube(100.0); glDisable(GL_LIGHTING); displayGrid(); // draws the floor }
The following example receives keyboard input
void MyBasicViewer::onKeyboard(unsigned char pKey, int x, int y) { ABasicViewer::onKeyboard(pKey, x, y); // needed for parent features to work std::cout << "You pressed the key: " << pKey << std::endl; }
And the following example shows how to update your animatable objects
void MyBasicViewer::onTimer(int timer) { double dt = mClock->totalElapsedTime(); ABasicViewer::onTimer(timer); // clears timer and increments mCurrentTime std::cout << "The simulation time is: " << mCurrentTime << " " << dt << std::endl; }
Then, to create and run the viewer, instantiate the viewer in main() and call run() to begin the application loop. The application runs until the user closes the window or quits the application.
include "MyBasicViewer.h" int main(int argc, char** argv) { MyBasicViewer viewer; viewer.init(argc, argv); viewer.run(); return 0; }To build a new application, you must update the cmake build files. These files correspond to the CMakeLists.txt files in each directory. The top level CMakeLists.txt file indicates which subdirectories to build using the add_subdirectory() command. For example, if you create a new directory called BonusAssignment, you should add it to the top level CMakeLists.txt file like so
cmake_minimum_required(VERSION 2.8.11) set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -DUNIX") set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) #for FindGLM.cmake, FindGLFW3.cmake, other helpers set (CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules) FIND_PACKAGE(OpenGL REQUIRED) #for graphics FIND_PACKAGE(GLEW REQUIRED) add_subdirectory(aBasicViewer) add_subdirectory(aCurveEditor) add_subdirectory(aRotations) add_subdirectory(aFKViewer) add_subdirectory(aIKViewer) add_subdirectory(aMotionBlend) add_subdirectory(libsrc) add_subdirectory(BonusAssignment)Then, inside the BonusAssignment directory, you will need to create a CMakeLists.txt file with build instructions for your new application. For example, suppose your new directory contains the source for MyBasicViewer.h, MyBasicViewer.cpp, and BasicMain.cpp. The corresponding CMakeLists.txt file would be
project(BonusAssignment) include_directories(../libsrc/animation ../libsrc/ui) link_directories(/usr/X11R6/lib libsrc/animation libsrc/ui) add_executable(BonusAssignment MyBasicViewer.cpp BasicMain.cpp) target_link_libraries(BonusAssignment animationik animationfk animationbasic animationcurve animationscurve ui AntTweakBar GLEW glut GL GLU X11)The above will build an executable called BonusAssignment and place the result in the /bin directory
> cd build > cmake .. ; make > ../bin/BonusAssignment
NOTE: If you're running out of space because of big files, try using the /local drive for temporary storage.
You will be asked to briefly checkin (less than 1 minute) about your homework assignment. This is not intended to much work. Please don't prepare slides or a voice over for your video. None of these are necessary! Some ideas of what you might like to talk about: