void _HandleAnimatedScale(Thread thread, int a, int b, ref BitVector scaleBeenSet) { int j = 0; int start = thread.Sequence.DoesScaleMatter.Start(); int end = b; // code the Scale conversion (might need to "upgrade" from uniform to arbitrary, e.g.) // code uniform, aligned, and arbitrary as 0,1, and 2, respectively, // with _sequence coding in first two bits, shape coding in Next two bits int code = 0; if (thread.Sequence.IsAlignedScaleAnimated()) code += 1; else if (thread.Sequence.IsArbitraryScaleAnimated()) code += 2; if (AnimatesAlignedScale()) code += 3; if (AnimatesArbitraryScale()) code += 6; float uniformScale = 1.0f; Vector3 alignedScale = new Vector3(1, 1, 1); ArbitraryScale arbitraryScale = new ArbitraryScale(); for (int nodeIndex = start; nodeIndex < end; thread.Sequence.DoesScaleMatter.Next(ref nodeIndex), j++) { if (nodeIndex < a) continue; if (!scaleBeenSet.Test(nodeIndex)) { // compute Scale in _sequence format switch (code) { case 0: // uniform -> uniform case 1: // uniform -> aligned case 2: // uniform -> arbitrary { float s1 = _shape.GetUniformScale(thread.Sequence, thread._keyNum1, j); float s2 = _shape.GetUniformScale(thread.Sequence, thread._keyNum2, j); uniformScale = Transform.Interpolate(s1, s2, thread._keyPos); alignedScale = new Vector3(uniformScale, uniformScale, uniformScale); break; } case 4: // aligned -> aligned case 5: // aligned -> arbitrary { Vector3 s1 = _shape.GetAlignedScale(thread.Sequence, thread._keyNum1, j); Vector3 s2 = _shape.GetAlignedScale(thread.Sequence, thread._keyNum2, j); Transform.Interpolate(s1, s2, thread._keyPos, out alignedScale); break; } case 8: // arbitrary -> arbitary { ArbitraryScale s1, s2; _shape.GetArbitraryScale(thread.Sequence, thread._keyNum1, j, out s1); _shape.GetArbitraryScale(thread.Sequence, thread._keyNum2, j, out s2); Transform.Interpolate(ref s1, ref s2, thread._keyPos, out arbitraryScale); break; } default: Assert.Fatal(false, "ShapeInstance.HandleAnimatedScale - Invalid sequence code."); break; } switch (code) { case 0: // uniform -> uniform { _nodeCurrentUniformScales[nodeIndex] = uniformScale; break; } case 1: // uniform -> aligned case 4: // aligned -> aligned { _nodeCurrentAlignedScales[nodeIndex] = alignedScale; break; } case 2: // uniform -> arbitrary case 5: // aligned -> arbitrary { _nodeCurrentArbitraryScales[nodeIndex].SetIdentity(); _nodeCurrentArbitraryScales[nodeIndex].Scale = alignedScale; break; } case 8: // arbitrary -> arbitary { _nodeCurrentArbitraryScales[nodeIndex] = arbitraryScale; break; } default: Assert.Fatal(false, "ShapeInstance.HandleAnimatedScale - Invalid sequence code."); break; } _workScaleThreads[nodeIndex] = thread; scaleBeenSet.Set(nodeIndex); } } }
void _AnimateVisibility(int ss) { if (_meshObjects.Length == 0) return; // find out who needs default values Set BitVector beenSet = new BitVector(); beenSet.SetSize(_meshObjects.Length); beenSet.SetAll(); for (int i = 0; i < _threadList.Count; i++) beenSet.TakeAway(_threadList[i].Sequence.DoesVisibilityMatter); // Set defaults int a = _shape.SubShapeFirstObject[ss]; int b = a + _shape.SubShapeObjectCount[ss]; for (int i = a; i < b; i++) { if (beenSet.Test(i)) _meshObjects[i].Visibility = _shape.ObjectStates[i].Visibility; } // go through each thread and Set visibility on those objects that // are not Set yet and are controlled by that thread BitVector objectMatters = new BitVector(); for (int i = 0; i < _threadList.Count; i++) { Thread th = _threadList[i]; objectMatters.Copy(ref th.Sequence.DoesFrameMatter); objectMatters.Overlap(th.Sequence.DoesMaterialFrameMatter); objectMatters.Overlap(th.Sequence.DoesVisibilityMatter); // skip to beginining of this sub-shape int j = 0; int start = objectMatters.Start(); int end = b; for (int objectIndex = start; objectIndex < b; objectMatters.Next(ref objectIndex), j++) { if (!beenSet.Test(objectIndex) && th.Sequence.DoesVisibilityMatter.Test(objectIndex)) { float state1 = _shape.GetObjectState(th.Sequence, th._keyNum1, j).Visibility; float state2 = _shape.GetObjectState(th.Sequence, th._keyNum2, j).Visibility; if ((state1 - state2) * (state1 - state2) > 0.99f) // goes from 0 to 1 -- discreet jump _meshObjects[objectIndex].Visibility = th._keyPos < 0.5f ? state1 : state2; else // Interpolate between keyframes when visibility change is gradual _meshObjects[objectIndex].Visibility = (1.0f - th._keyPos) * state1 + th._keyPos * state2; // record change so that later threads don't over-write us... beenSet.Set(objectIndex); } } } }
void _AnimateMatFrame(int ss) { if (_meshObjects.Length == 0) return; // find out who needs default values Set BitVector beenSet = new BitVector(); beenSet.SetSize(_meshObjects.Length); beenSet.SetAll(); for (int i = 0; i < _threadList.Count; i++) beenSet.TakeAway(_threadList[i].Sequence.DoesMaterialFrameMatter); // Set defaults int a = _shape.SubShapeFirstObject[ss]; int b = a + _shape.SubShapeObjectCount[ss]; for (int i = a; i < b; i++) { if (beenSet.Test(i)) _meshObjects[i].MaterialFrame = _shape.ObjectStates[i].MaterialFrameIndex; } // go through each thread and Set matFrame on those objects that // are not Set yet and are controlled by that thread BitVector objectMatters = new BitVector(); for (int i = 0; i < _threadList.Count; i++) { Thread th = _threadList[i]; objectMatters.Copy(ref th.Sequence.DoesFrameMatter); objectMatters.Overlap(th.Sequence.DoesMaterialFrameMatter); objectMatters.Overlap(th.Sequence.DoesVisibilityMatter); // skip to beginining of this sub-shape int j = 0; int start = objectMatters.Start(); int end = b; for (int objectIndex = start; objectIndex < end; objectMatters.Next(ref objectIndex), j++) { if (!beenSet.Test(objectIndex) && th.Sequence.DoesMaterialFrameMatter.Test(objectIndex)) { int key = (th._keyPos < 0.5f) ? th._keyNum1 : th._keyNum2; _meshObjects[objectIndex].MaterialFrame = _shape.GetObjectState(th.Sequence, key, j).MaterialFrameIndex; // record change so that later threads don't over-write us... beenSet.Set(objectIndex); } } } }
void _AnimateNodes(int ss) { if (_shape.Nodes.Length == 0) return; // temporary storage for node transforms int numNodes = _shape.Nodes.Length; if (_nodeCurrentRotations == null || _nodeCurrentRotations.Length < numNodes) { // grow all these arrays together...no need to check each individually TorqueUtil.GrowArray<Quaternion>(ref _nodeCurrentRotations, numNodes); TorqueUtil.GrowArray<Vector3>(ref _nodeCurrentTranslations, numNodes); TorqueUtil.GrowArray<Thread>(ref _workRotationThreads, numNodes); TorqueUtil.GrowArray<Thread>(ref _workTranslationThreads, numNodes); } BitVector rotBeenSet = new BitVector(); BitVector tranBeenSet = new BitVector(); BitVector scaleBeenSet = new BitVector(); rotBeenSet.SetSize(numNodes); rotBeenSet.SetAll(); tranBeenSet.SetSize(numNodes); tranBeenSet.SetAll(); scaleBeenSet.SetSize(numNodes); scaleBeenSet.SetAll(); int firstBlend = _threadList.Count; for (int i = 0; i < _threadList.Count; i++) { Thread th = _threadList[i]; if (th.Sequence.IsBlend()) { // blend sequences need default (if not Set by other _sequence) // break rather than continue because the rest will be blends too firstBlend = i; break; } rotBeenSet.TakeAway(th.Sequence.DoesRotationMatter); tranBeenSet.TakeAway(th.Sequence.DoesTranslationMatter); scaleBeenSet.TakeAway(th.Sequence.DoesScaleMatter); } rotBeenSet.TakeAway(_handsOffNodes); tranBeenSet.TakeAway(_handsOffNodes); // all the nodes marked above need to have the default transform int a = _shape.SubShapeFirstNode[ss]; int b = a + _shape.SubShapeNodeCount[ss]; for (int i = a; i < b; i++) { if (rotBeenSet.Test(i)) { _shape.DefaultRotations[i].Get(out _nodeCurrentRotations[i]); _workRotationThreads[i] = null; } if (tranBeenSet.Test(i)) { _nodeCurrentTranslations[i] = _shape.DefaultTranslations[i]; _workTranslationThreads[i] = null; } } // don't want a transform in these cases... rotBeenSet.Overlap(_handsOffNodes); tranBeenSet.Overlap(_handsOffNodes); // default Scale if (ScaleCurrentlyAnimated()) _HandleDefaultScale(a, b, ref scaleBeenSet); // handle non-blend sequences for (int i = 0; i < firstBlend; i++) { Thread th = _threadList[i]; int nodeIndex = th.Sequence.DoesRotationMatter.Start(); int end = b; for (int j = 0; nodeIndex < end; th.Sequence.DoesRotationMatter.Next(ref nodeIndex), j++) { // skip nodes outside of this detail if (nodeIndex < a) continue; if (!rotBeenSet.Test(nodeIndex)) { Quaternion q1, q2; _shape.GetRotation(th.Sequence, th._keyNum1, j, out q1); _shape.GetRotation(th.Sequence, th._keyNum2, j, out q2); Transform.Interpolate(q1, q2, th._keyPos, out _nodeCurrentRotations[nodeIndex]); rotBeenSet.Set(nodeIndex); _workRotationThreads[nodeIndex] = th; } } nodeIndex = th.Sequence.DoesTranslationMatter.Start(); end = b; for (int j = 0; nodeIndex < end; th.Sequence.DoesTranslationMatter.Next(ref nodeIndex), j++) { if (nodeIndex < a) continue; if (!tranBeenSet.Test(nodeIndex)) { Vector3 p1 = _shape.GetTranslation(th.Sequence, th._keyNum1, j); Vector3 p2 = _shape.GetTranslation(th.Sequence, th._keyNum2, j); Transform.Interpolate(p1, p2, th._keyPos, out _nodeCurrentTranslations[nodeIndex]); _workTranslationThreads[nodeIndex] = th; tranBeenSet.Set(nodeIndex); } } if (ScaleCurrentlyAnimated()) _HandleAnimatedScale(th, a, b, ref scaleBeenSet); } // transitions... if (InTransition()) _HandleTransitionNodes(a, b); // compute transforms for (int i = a; i < b; i++) if (!_handsOffNodes.Test(i)) Transform.SetMatrix(_nodeCurrentRotations[i], _nodeCurrentTranslations[i], out _nodeTransforms[i]); // add Scale onto transforms if (ScaleCurrentlyAnimated()) _HandleNodeScale(a, b); // get callback transforms... if (_callbackNodes != null) for (int i = 0; i < _callbackNodes.Count; i++) _callbackNodes[i].Transform.GetLocalMatrix(out _nodeTransforms[_callbackNodes[i].NodeIndex], true); // handle blend sequences for (int i = firstBlend; i < _threadList.Count; i++) { Thread th = _threadList[i]; if (th._blendDisabled) continue; _HandleBlendSequence(th, a, b); } // multiply transforms... for (int i = a; i < b; i++) { int parentIdx = _shape.Nodes[i].ParentIndex; if (parentIdx >= 0) _nodeTransforms[i] = Matrix.Multiply(_nodeTransforms[i], _nodeTransforms[parentIdx]); } }
void _HandleDefaultScale(int a, int b, ref BitVector scaleBeenSet) { // Set default Scale values (i.e., SetIdentity) and do any initialization // relating to animated Scale (since Scale normally not animated) int numNodes = _shape.Nodes.Length; TorqueUtil.GrowArray<Thread>(ref ShapeInstance._workScaleThreads, numNodes); scaleBeenSet.TakeAway(_handsOffNodes); if (AnimatesUniformScale()) { TorqueUtil.GrowArray<float>(ref ShapeInstance._nodeCurrentUniformScales, numNodes); for (int i = a; i < b; i++) if (scaleBeenSet.Test(i)) { ShapeInstance._nodeCurrentUniformScales[i] = 1.0f; ShapeInstance._workScaleThreads[i] = null; } } else if (AnimatesAlignedScale()) { TorqueUtil.GrowArray<Vector3>(ref ShapeInstance._nodeCurrentAlignedScales, numNodes); for (int i = a; i < b; i++) if (scaleBeenSet.Test(i)) { ShapeInstance._nodeCurrentAlignedScales[i] = new Vector3(1.0f, 1.0f, 1.0f); ShapeInstance._workScaleThreads[i] = null; } } else { TorqueUtil.GrowArray<ArbitraryScale>(ref ShapeInstance._nodeCurrentArbitraryScales, numNodes); for (int i = a; i < b; i++) if (scaleBeenSet.Test(i)) { _nodeCurrentArbitraryScales[i].SetIdentity(); _workScaleThreads[i] = null; } } scaleBeenSet.Overlap(_handsOffNodes); }