LECTURE 12 Announcements 1 down, 3 to go! • Final1, and ~2/3 of your engines, are done! • No playtesting today • Engines should be totally done by next Wednesday • Games should be “playable” by then • Meet and form Final 2 and 3 rubrics today or tomorrow No more regular hours • Go to your mentor TA with any final-related problems • E-mail the TA list for any non-final related problems – Warmup / minecraft / platformer related questions – We’ll set up a meeting that works time-wise No Credit Assignments Reminder • No credit assignments must be turned in and graded complete by Final 5 – May 17th • Don’t wait until that week! – What if you don’t get it first try? – We don’t want to give anyone an NC Playtesting moving forward • You *must* have a /contrib project – Update it just before playtesting – Or whenever else you like • We will no longer publish demos • This will help in your own public playtesting anyway • Link on how here Contrib Install Script #!/bin/bash echo 'Installing <project> to contrib - make sure you are in the build directory!' contrib_dir='/contrib/projects/<project>' echo 'Copying <important file>...' cp <important file> $contrib_dir Announcements QUESTIONS? LECTURE 12 Portals Portals RENDERING PORTALS What are portals? • Visual – Look at one place, see another • Logical – Teleport from one place to another • Physical – Momentum transfers from one place to another Logical/Physical Problems • Space discontinuities are tricky – They don’t exist in the real world • When has an entity “passed” through a portal? – When it’s center passes through? – When it first touches the portal? – When it’s full collision shape is through the portal? • Does the same entity exist in 2 place? – Can be collided with from both sides? • Can other things travel through portals? – Raycasts? Pathfinding? Portals – rendering overview • The process for rendering portals is simple: – Decide where on the screen to draw (stencil buffer) – Figure out where & from what angle to draw the portal’s perspective – Draw the world on the other side of the portal The Stencil Buffer • Determines the drawable areas on the screen • After setting up, use normal 3D draw calls – ex. for a rectangular portal, just draw the 3D rectangle as though it were a shape in the scene Using the Stencil Buffer • Steps in psuedocode: Enable stencil testing Change drawing masks (disable color, enable stencil drawing) Draw your 3D portal shapes so they appear in the stencil buffer Revert your drawing masks to normal rendering Tell OpenGL how to interpret your stencil buffer Ready for drawing! Setting up the proxy camera • Calculate your camera’s offset from the portal you see • Account for rotations of the two portals • Subtract the result from the paired portal’s position Clipping the scene • In this example, the proxy camera is behind a wall • A free-standing portal might have objects between it and the proxy camera Clipping the scene • You’ll see objects in the portal that seem closer than the actual portal • Great if your final feature is IMAX (0 pts) • Not so good for portals Clipping the scene • Good news – you’ve done this before with view frustum culling • You just need to add and test against another clipping plane – Your plane should only accept things in front of the paired portal’s face – Yes, you might need to review the math for planes Clipping the scene • You could also create the full view frustum through the portal from your eye – This is actually a whole rendering technique called portal culling – This part isn’t necessary but it is a significant optimization Yellow is the eye frustum Red is the frustum of the first portal Blue and Pink are the frustums two portals deep More uses for stencil buffers • This technique allows you to render any part of any scene in a region of your current screen – Mirrors are just 2 portals to the same location, in the opposite direction – You could implement doors and windows between indoor/outdoor worlds as portals – You could make a CCTV (like a security camera) to another part of your level • Think “one-way” portal Portal Tips • Start simple – implement portals facing in the same direction, or in axis-aligned directions, so you know your rendering code works before you have to debug arbitrary rotations. • Drawing the portal scene replaces the existing depth buffer – If you draw your portals in the middle of your rendering, they and everything drawn afterwards will not be occluded by anything drawn before them. • Great resource for portals & stencil buffer: https://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal Portals QUESTIONS? LECTURE 12 Animation Animation SKELETAL ANIMATION Skeletal Animation • Consists of joints and/or bones to represent parts of the object • By itself, provides no shape deformation, only translation & rotation Skeletal Animation • This works great in minecraft, where everything is a rectangular prism anyways • It can work with arbitrary mesh pieces too – Just watch out for meshes intersecting Example Joint System • Create a root joint, then hierarchically add joints with fixed offsets – the space between root and child joints is the ‘bone’ area – assign mesh(s) to render at each joint or bone – keep track of the rotation(s) active at each joint • You should only need three (x, y, z axes of rotation) Hierarchical Joint Systems • OpenGL can perform the rendering rotations for you easily • It’s not a ton of work to set up – expect to spend a good amount of time on content creation to make animations that look nice Animating joints • Think of some tools that you can use to specify an animation – Keyframes (or timers) • At time t0, joint j3 rotation x is x0 • At time t1, joint j3 rotation x is x1 (w/ linear interpolation) • At time t2, joint j3 rotation x is x2 (w/ quadratic interp) – Programs like Maya have these features and many more – look for inspiration to make something complex Animating joints – Functions • Set joint’s rotation y to A*sin(B*time) (rotate in a circle) • Might be useful for a looping walk animation – Combination of tools • Ex. Joints animate with a function while character is moving, then interpolate back to resting position – Abstraction: build small animation pieces (ex. ‘swingArms’, ‘bounceTail’) and combine them for more complex behaviors – Inverse Kinematics • Just kidding Skeletal Animation QUESTIONS? Animation RIGGED MESH ANIMATION Rigged Animation • Consists of a skin (mesh) binding on top of a skeletal/joint system • Useful for any animation that deforms a mesh Rigged Animation • Given a set of vertices representing your mesh, and a set of joints or bones: – Determine which vertices correspond to which bones – Determine how much weight each bone has on its vertices – Calculate how the changing bone positions affect the vertices they influence • The first two are probably content creation, the last is your engine feature Rigged Animation • Manipulating vertices with bones: – Each vertex has a vector offset from each bone it is attached to – As the bone translates around, maintain that same offset for each vertex – As the bone rotates, apply that rotation to each vertex with its offset – This may be slow for a detailed model • Look into using matrices to speed up the computations • Use a program like Maya to optimize your models Rigging (Skinning) a Mesh • Skinning is the technical process of assigning bone/joint ‘weights’ to each vertex • Each vertex can have up to a set number (usually around 3-4) bones that affect it • Traditionally, this would be done by hand in a program like Maya – An algorithm assigns initial weights with some heuristic – The animator then tweaks these weights to look right Rigging (Skinning) a Mesh • You should implement your own algorithm for assigning bones, then try tweaking the weights – Start with a basic distance heuristic (assign vertices to the bone(s) closest to them) – Add conditions, such as: multiple bones affecting a vertex should be hierarchically connected These vertices might choose the wrong leg bone as the 3rd closest bone Case Study – Unity Locomotion • • • • • Unity library for realistic movement Sets pose of skeleton procedurally Blends between animations: up vs down slopes Places feet tangent to surface Video! Rigged Mesh Animation QUESTIONS? An aside – ragdoll physics • Blending of physics and animation • Rigid bodies tied together by constraints – Typically spring-damper constraints • Many variations on standard approach: – Verlet integration: Model each bone as a point – Blended ragdoll: Use preset animation, but constrain output based on a model of a physical system • Used in Halo 2, Halo 3, Left 4 Dead, etc. Euphoria and Endorphin • Euphoria – ragdoll physics engine used in GTA IV, Red Dead Redemption, Star Wars: The Force Unleash, etc… • Endorphin – animation engine built on top of Euphoria providing “intelligent” procedural animations • Video! LECTURE 12 C++ Tip of the Week C++ tip of the week • Multiple inheritance – C++ classes can have multiple superclasses – Can be used to emulate Java interfaces // Declare interfaces using pure virtual functions struct Reader { virtual char read() = 0; }; struct Writer { virtual void write(char) = 0; }; // File * can be dynamic_cast to Reader * and Writer * struct File : Reader, Writer { char read() { ... } void write(char) { ... } }; C++ tip of the week • More powerful than Java interfaces – All superclasses can have state struct Timestamp { const long creationTime; Timestamp() : creationTime(time(NULL)) {} }; struct UniqueID { const int id; static int nextID; UniqueID() : id(nextID++) {} }; struct Entity : Timestamp, UniqueID {}; C++ tip of the week • The diamond problem struct struct struct struct Base { int num; }; Derived1 : Base {}; Derived2 : Base {}; Join : Derived1, Derived2 {}; Base Base Derived1 Derived2 Join Join cout cout cout join; << join.num; // error, join has two copies of num << join.Derived1::num; << join.Derived2::num; C++ tip of the week • Can be mitigated with virtual inheritance Base struct struct struct struct Base { int num; }; Derived1 : virtual Base {}; Derived2 : virtual Base {}; Join : Derived1, Derived2 {}; Derived1 Derived2 Join Join join; cout << join.num; // works, only one copy of Base and num C++ tip of the week • Tricky case – Multiple implementations of foo in Join (base1 != base2) – Using virtual inheritance here would cause an error struct struct struct struct Join Base Base Base Base { virtual void foo() = 0; }; Derived1 : Base { void foo() { cout << 1; } }; Derived2 : Base { void foo() { cout << 2; } }; Join : Derived1, Derived2 {}; join; *base = &join; // error, ambiguous conversion *base1 = static_cast<Derived1 *>(&join); *base2 = static_cast<Derived2 *>(&join); C++ tip of the week • Tricky case – Fix: define the behavior we want by overriding foo() again in the class with multiple inheritance struct struct struct struct void }; Base { virtual void foo() = 0; }; Derived1 : virtual Base { void foo() { /*...*/ } }; Derived2 : virtual Base { void foo() { /*...*/ } }; Join : Derived1, Derived2 { foo() { Derived1::foo(); Derived2::foo(); } Join join; Base *base = &join; // works, only one foo() implementation C++ Tip of the Week QUESTIONS? NO PLAYTESTING Get good work done this week so next week’s playtesting is awesome!