internal List <float> GetTimesForBone(string bone, library_visual_scenes lvs) { List <float> ret = new List <float>(); foreach (channel chan in mChannels) { //extract the node name and address int sidx = chan.target.IndexOf('/'); string sid = chan.target.Substring(0, sidx); //ok this is tricky, the spec says that the <source> //referenced by the input with the JOINT semantic //should contain a <Name_array> that contains sids //to identify the joint nodes. sids are used instead //of IDREFs to allow a skin controller to be instantiated //multiple times, where each instance can be animated //independently. // //So max's default collada exporter doesn't even give the //bones sids at all, and the other one whose name escapes //me gives the bones sids, but then the address element //says Name (note the case), so I guess you need to try //to match via sid first and if that fails, use name? node n = AnimForm.LookUpNode(lvs, sid); if (n == null) { continue; } if (bone != n.name) { continue; } //grab sampler key string sampKey = chan.source; //strip # sampKey = sampKey.Substring(1); sampler samp = mSamplers[sampKey]; string srcInp = GetSourceForSemantic(samp, "INPUT"); float_array srcTimes = mSources[srcInp].Item as float_array; foreach (float time in srcTimes.Values) { float t = time; if (ret.Contains(t)) { continue; } ret.Add(t); } } return(ret); }
internal Animation.KeyPartsUsed SetKeys(string bone, List <float> times, List <MeshLib.KeyFrame> keys, library_visual_scenes scenes, List <MeshLib.KeyFrame> axisAngleKeys) { Animation.KeyPartsUsed ret = 0; foreach (channel chan in mChannels) { //extract the node name and address int sidx = chan.target.IndexOf('/'); string sid = chan.target.Substring(0, sidx); node n = AnimForm.LookUpNode(scenes, sid); if (n == null) { continue; } if (bone != n.name) { continue; } //grab sampler key string sampKey = chan.source; //strip # sampKey = sampKey.Substring(1); sampler samp = mSamplers[sampKey]; string srcInp = GetSourceForSemantic(samp, "INPUT"); string srcOut = GetSourceForSemantic(samp, "OUTPUT"); string srcC1 = GetSourceForSemantic(samp, "IN_TANGENT"); string srcC2 = GetSourceForSemantic(samp, "OUT_TANGENT"); float_array chanTimes = mSources[srcInp].Item as float_array; float_array chanValues = mSources[srcOut].Item as float_array; List <float> outValues = new List <float>(); int numChanKeys = chanValues.Values.Length; numChanKeys /= (int)mSources[srcOut].technique_common.accessor.stride; Debug.Assert(numChanKeys == (int)chanTimes.count); //grab values for this channel //along the overall list of times for (int tidx = 0; tidx < times.Count; tidx++) { outValues.AddRange(LerpValue(times[tidx], chanTimes, chanValues, (int)mSources[srcOut].technique_common.accessor.stride)); } int slashIndex = chan.target.IndexOf("/"); string nodeID = chan.target.Substring(0, slashIndex); string nodeElement = chan.target.Substring(slashIndex + 1); //see if the element has an additional address string addr = null; int dotIdx = nodeElement.IndexOf('.'); if (dotIdx != -1) { addr = nodeElement.Substring(dotIdx + 1); nodeElement = nodeElement.Substring(0, dotIdx); } node targeted = AnimForm.LookUpNode(scenes, nodeID); int idx = AnimForm.GetNodeItemIndex(targeted, nodeElement); if (idx == -1) { continue; //bad anim stuffs? } if (targeted.ItemsElementName[idx] == ItemsChoiceType2.lookat) { Debug.Assert(false); //haven't dealt with this one yet } else if (targeted.ItemsElementName[idx] == ItemsChoiceType2.matrix) { //this doesn't really work yet List <Matrix> mats = AnimForm.GetMatrixListFromFloatList(outValues); for (int v = 0; v < mats.Count; v++) { mats[v].Decompose(out keys[v].mScale, out keys[v].mRotation, out keys[v].mPosition); } ret |= Animation.KeyPartsUsed.All; } else if (targeted.ItemsElementName[idx] == ItemsChoiceType2.rotate) { if (addr == null) { //I'm guessing these would be true quaternions //I don't really support that, as I store the //usual axis angle stuff I've seen in a quaternion //and then later fix it up to be a real quaternion Debug.Assert(false); } else if (addr == "ANGLE") { Debug.Assert(targeted.Items[idx] is rotate); rotate rot = targeted.Items[idx] as rotate; if (rot.Values[0] > 0.999f) { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mRotation.X = val; if (!axisAngleKeys.Contains(keys[v])) { axisAngleKeys.Add(keys[v]); } } ret |= Animation.KeyPartsUsed.RotateX; } else if (rot.Values[1] > 0.999f) { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mRotation.Y = val; if (!axisAngleKeys.Contains(keys[v])) { axisAngleKeys.Add(keys[v]); } } ret |= Animation.KeyPartsUsed.RotateY; } else if (rot.Values[2] > 0.999f) { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mRotation.Z = val; if (!axisAngleKeys.Contains(keys[v])) { axisAngleKeys.Add(keys[v]); } } ret |= Animation.KeyPartsUsed.RotateZ; } else { Debug.Assert(false); //broken! } } } else if (targeted.ItemsElementName[idx] == ItemsChoiceType2.scale) { if (addr == null) { //I haven't seen this happen, but I'm guessing it //would be vector3s for (int v = 0; v < outValues.Count; v += 3) { keys[v / 3].mScale.X = outValues[v]; keys[v / 3].mScale.Y = outValues[v + 1]; keys[v / 3].mScale.Z = outValues[v + 2]; } ret |= Animation.KeyPartsUsed.ScaleX; ret |= Animation.KeyPartsUsed.ScaleY; ret |= Animation.KeyPartsUsed.ScaleZ; } else if (addr == "X") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mScale.X = val; } ret |= Animation.KeyPartsUsed.ScaleX; } else if (addr == "Y") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mScale.Y = val; } ret |= Animation.KeyPartsUsed.ScaleY; } else if (addr == "Z") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mScale.Z = val; } ret |= Animation.KeyPartsUsed.ScaleZ; } } else if (targeted.ItemsElementName[idx] == ItemsChoiceType2.skew) { Debug.Assert(false); //haven't dealt with this one yet } else if (targeted.ItemsElementName[idx] == ItemsChoiceType2.translate) { if (addr == null) { //the values are vector3s in this case for (int v = 0; v < outValues.Count; v += 3) { keys[v / 3].mPosition.X = outValues[v]; keys[v / 3].mPosition.Y = outValues[v + 1]; keys[v / 3].mPosition.Z = outValues[v + 2]; } ret |= Animation.KeyPartsUsed.TranslateX; ret |= Animation.KeyPartsUsed.TranslateY; ret |= Animation.KeyPartsUsed.TranslateZ; } else if (addr == "X") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mPosition.X = val; } ret |= Animation.KeyPartsUsed.TranslateX; } else if (addr == "Y") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mPosition.Y = val; } ret |= Animation.KeyPartsUsed.TranslateY; } else if (addr == "Z") { for (int v = 0; v < outValues.Count; v++) { float val = outValues[v]; keys[v].mPosition.Z = val; } ret |= Animation.KeyPartsUsed.TranslateZ; } } } return(ret); }