How do I insert time into my Maya animation timeline - animation

I frequently get myself into trouble when I've put together a complex animation in Maya with lots of rigs and connections and animated attributes and then find that I need to insert 100 frames somewhere in my 5000 frame animation to make space for additional animation. In the past, I've struggled with selecting all objects and all of their keyframes to move them down the timeline as it seems that I always miss some attributes that don't get moved and then things get ugly and I waste a lot of time fixing things.
I feel like there must be a more elegant way to insert a certain number of frames into the timeline easily without worrying that some keyframes will be left behind. I've tried my luck with the dope sheet, but I don't really find it any easier to use than the graph editor.

"Elegant" in this case is in the eye of the beholder.
Effectively what you need to do is move all the keys after a given point by a given amount. The hard part is that moving the keys will change the meaning of the curves: the interpolation is going to change no matter what you do unless you've got locked tangents on both sides of the change.
if you just want to insert keys at a particular point in time, it'll look like this:
def move_keys_after(start, time_shift):
key_string = '%s:' % start
for curve in cmds.ls(type='animCurve'):
before = cmds.keyframe(curve, q=True)
cmds.keyframe(curve, r = True, tc = time_shift, t = (key_string,), iub=True)
after = cmds.keyframe(curve, q=True)
print curve, before, "->", after
move_keys_after( 10, 20)
That example moves all of the keys in the scene after time start by time_shift frames. If you want to limit this to an object you could get the anim curves from the object directly or use the animation flag of the keyframe command

Related

How to not change other attributes while animating in Maya?

I am trying to change the scale and rotation of my object in specific key frames but it changes the object attributes throughout the animation and I do not want that,how do I resolve this problem?
I know its a stupid question but could not figure it out on my own ,so here we go...
Thinking about your question, without much information to go by, there could be a few reasons for your unexpected results.
attributes in question have no keyframe, changing the value is static during the animation and therefore will reflect on the whole time range. If an attribute is not highlighted with a red color in the channel box, then no keyframes exist on that channel.
your previous and next keyframe could be very far apart and the blend could therefore be creating undesired results. Add keyframes closer to the frame you keyed to have a shorter blend from one value to the other.
if you are looking for very quick and not blended changes in values, try setting the curves to stepped instead of linear blend. Even there you will have to have at least more than one key to have a change of value during the animation.
if you are working with animation layers, check whether you you are in additive or overwrite mode. In both cases you might have to create multiple keys.
in the bottom right of Maya there is a button called "Auto Keyframe". This one will create keyframes automatically when you change values, but will do so only on already keyed channels.
use the graph editor to see what's going on with your curves for the attributes in question (Windows - Animation - Graph Editor). Don't rely on the red ticks in the main timeline, as you can only see whether a keyframe exists but you can't tell for which attribute(s).

A better way to roll dice

I have a game that requires the player to roll two die. As this is a multiplayer game, the way I currently do this is have 6 animations (1 for each die's outcome). When the player clicks a button, it sends a request to my server code. My server code determines the die's outcome and sends the results to the client. The client then plays the corresponding animations.
This works ok, but has some issues. For instance, if the server sends back two of the same values (two 6's, for example) then the animations don't work correctly. As both animations are the same, they overlay each other, and it looks like only one die was rolled.
Is there a better way to do this? Instead of animations, using "real" dice? If that's the case, I always need to be sure to "pre-determine" the outcome of the dice roll, on the server. I also need to make sure the dice don't fall off the table or jostle any of the other player pieces on the board.
thanks for any ideas.
The server only needs to care about the value result, not running physics calculations.
Set up 12 different rolling animations:
Six for the first die
Six for the second die
Each one should always end with the same modeled face pointing upwards (the starting position isn't relevant, only the ending position). For the latter steps you'll probably want to adjust the model's UV coordinates to use a very tall or very wide texture (or just a slice of a square one). So not like this but rather all in a line 1-2-3-4-5-6.
The next step is picking a random animation to play. You've already got code to run a given animation, just set it to pick randomly instead of based on the die-roll-value from the server:
int animNum = Mathf.Floor(Random.Next()*6);
Finally, the fun bit. Adjusting the texture so that the desired face shows when the animation is done. I'm going to assume that you arrange your faces along the top edge of your square texture. Material.SetTextureOffset().
int showFace = Mathf.Floor(Random.Next()*6); //this value should come from the server
die.renderer.material.SetTextureOffset(1f/6 * showFace,0);
This will set the texture offset such that the desired face will show on top. You'll even be able to see it changing in the inspector. Because of the UVs being arranged such that each face uses the next chunk over and because textures will wrap around when reaching the edge (unless the texture is set to Clamp in its import settings: you don't want this here).
Note that this will cause a new material instance to be instantiated (which is not very performant). If you want to avoid this, you'll have to use a material property block instead.
You could simulate the physics on the server, keep track of the positions and the orientations of the dice for the duration of the animation, and then send the data over to the client. I understand it's a lot of data for something so simple, but that's one way you can get the rolls to appear realistic and synced between all clients.
If only Unity's physics was deterministic that would be a whole lot easier.

Pixi.js: Animate circle (improving performance)

I would like to animate 1000 circles (position, radius, alpha, fill, stroke).
The current method I am using involves updating some properties on the Graphics object but then also clearing and recreating the circle for each draw().
holder = new PIXI.Graphics();
holder.lineStyle(strokeWidth, strokeColor, strokeOpacity);
holder.beginFill(color);
holder.drawCircle(r, r, r);
holder.endFill();
This is unfortunately too expensive ... Is there any way to avoid clearing the circle or another approach that can speed this render loop up?
if you hold a reference on each holder (for example in an array) you just can update their positions / tinting etc.. on each loop.
You can try a couple of things to improve performance:
Make sure that you only use one PIXI.Graphics (or as least as possible objects) object which is created on initialisation and not on every animFrame. Draw all of the circles on that object and only manipulate those.
If you don't have to change properties on every single circle try to group similar ones and you can generateTexture from them which then still allows you to manipulate position, size and alpha.
Try to limit updating the circles so it doesn't happen on every draw. Do you really need 60 updates per second? If you do, try to group circles and update for example 100 of them in one frame, next 100 in next frame and so on...
I'm not sure what exactly do you want to achieve with 1000 circles but if you add an example to your questions I can be more specific with optimisation tips.

Three js performance

Hy!
I am working with huge vertice objects, I am able to show lots of modells, because I have split them into smaller parts(Under 65K vertices). Also I am using three js cameras. I want to increase the performance by using a priority queue, and when the user moving the camera show only the top 10, then when the moving stop show the rest. This part is not that hard, but I dont want to put modells to render, when they are behind another object, maybe send out some Rays from the view of the camera(checking the bounding box hit) and according hit list i can build the prior queue.
What do you think?
Also how can I detect if I can load the next modell or not.(on the fly)
Option A: Occlusion culling, you will need to find a library for this.
Option B: Use a AABB Plane test with camera Frustum planes and object bounding box, this will tell you if an object is in cameras field of view. (not necessarily visible behind object, as such a operation is impossible, this mostly likely already done to a degree with webgl)
Implementation:
Google it, three js probably supports this
Option C: Use a max object render Limit, prioritized based on distance from camera and size of object. Eg Calculate which objects are visible(Option B), then prioritize the closest and biggest ones and disable the rest.
pseudo-code:
if(object is in frustum ){
var priority = (bounding.max - bounding.min) / distanceToCamera
}
Make sure your shaders are only doing one pass. As that will double the calculation time(roughly depending on situation)
Option D: raycast to eight corners of bounding box if they all fail don't render
the object. This is pretty accurate but by no means perfect.
Option A will be the best for sure, Using Option C is great if you don't care that small objects far away don't get rendered. Option D works well with objects that have a lot of verts, you may want to raycast more points of the object depending on the situation. Option B probably won't be useful for your scenario, but its a part of c, and other optimization methods. Over all there has never been an extremely reliable and optimal way to tell if something is behind something else.

What is the best way of making concurrent animations?

this is an algorithm/data structure question about making different animations at the same time. For example, a ball is falling down one pixel in a millisecond, a bullet is moving 5 pixels in a ms, and a man is moving 1 pixel in 20 milliseconds. And think that there are hundreds of them together. What is the best way of putting all animations together, moving what we need to move in one function call, and removing the ones whose animation is completed? I don't want to create a thread for each one. What I want to do is to create one thread moving all items and sleeping until an object needs to be moved.
Note: I'm using Java/Swing, printing objects and images in JPanel.
I recently did something similar in Python. I don't know if this is the best method, but here's what I did.
Create an abstract Event class with the following public interface:
tick - calculates how much time has passed since the last tick. Perform work proportional to that time span. This should be called frequently to create the illusion of smooth movement; maybe sixteen times a second or so.
isDone - returns true when the Event has finished occuring.
Make a subclass of Event for anything that takes more than one frame to finish. Rotating, scaling, color changing, etc. You might create a TweenEvent subclass of Event if you want to move an image from one part of the screen to another. During each tick, redraw the image in a position farther away from the original position, and farther towards the destination position.
You can run many Events concurrently, like so:
Array<Event> events = new Array<Event>();
//add a bunch of TweenEvents here - one for a bullet, one for a ball, etc.
while(True){
Sleep(1/16);
for(Event e in events){
e.tick();
if (e.isDone()){events.remove(e);}
}
}

Resources