private void BuildAnimations(ModelDocument dest) { foreach (var seq in sequences) { var a = new ModelAnimation() { Name=seq.label }; if (seq.blends != null) { int blend = 0; //IList<ModelAnimationFrameBone>[] = b var f = new ModelAnimationFrame() { Time=0}; a.Frames.Add(f); for (int bone = 0; bone < bones.Count; ++bone) { mstudioanim_t animBlend = seq.blends[blend, bone]; f.Bones.Add(new ModelAnimationFrameBone() {Bone=modelBones[bone],Position=modelBones[bone].Position,Rotation=modelBones[bone].Rotaton }); } f = new ModelAnimationFrame() { Time = 1 }; a.Frames.Add(f); for (int bone = 0; bone < bones.Count; ++bone) { mstudioanim_t animBlend = seq.blends[blend, bone]; f.Bones.Add(new ModelAnimationFrameBone() { Bone = modelBones[bone], Position = modelBones[bone].Position, Rotation = modelBones[bone].Rotaton }); } } dest.Animations.Add(a); } }
public void StopAnim(string animationName) { if (AnimPlayer.useMeshAnimation) { ModelAnimation.Stop(base.gameObject, this.meshanim, this.MeshAnimationRes, animationName); } }
//render methods public void Render(Camara cam, ModelAnimation model) { //make a copy, don't touch original points to keep accuracy Vector3 tmpVertex1 = Vertex1; Vector3 tmpVertex2 = Vertex2; Vector3 tmpVertex3 = Vertex3; //move the vertexs in local space ScaleVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, model.scale); TranslateVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, model.location); RotateVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, model.angle); //move the vertexs in world space TranslateVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, cam.location); RotateVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, cam.angle); //culling/drawing/perspective if (!InZRange(tmpVertex1, tmpVertex2, tmpVertex1, cam)) { return; } if (!model.orthographic) { PerspectiveVertexs(ref tmpVertex1, ref tmpVertex2, ref tmpVertex3, cam); } if (!OnScreen(tmpVertex1, tmpVertex2, tmpVertex1, cam)) { return; } DrawTriangle(tmpVertex1, tmpVertex2, tmpVertex1, model, cam); }
public void PlayAnimate(string animationName, WrapMode wrapMode) { if (AnimPlayer.useMeshAnimation) { this.playingAnimation = animationName; ModelAnimation.Play(base.gameObject, this.meshanim, this.MeshAnimationRes, animationName, wrapMode, 1.2f, false); } }
public void PlayAnimation(string path, string name, int rate, WrapMode mode, float fSpeed, int iFrameIndex) { this.dummys = ModelAnimation.s_dummy[path + "/" + name]; MeshClip1 meshClips = ModelAnimation.getMeshClips(this.m_ctrl, path + "/" + name); if (meshClips != null) { this.PlayAnimation(meshClips, rate, mode, fSpeed, iFrameIndex); } }
} // WrapMode #endregion #region Constructor /// <summary> /// The AnimationState gives full control over animation blending. /// </summary> /// <remarks> /// In most cases the Animation interface is sufficient and easier to use. /// Use the AnimationState if you need full control over the animation blending any playback process. /// The AnimationState interface allows you to modify speed, weight, time and layers while any animation is playing. /// You can also setup animation mixing and wrapMode. /// </remarks> public AnimationState(ModelAnimation modelAnimation) { this.modelAnimation = modelAnimation; enabled = true; weight = 1; time = 0; speed = 1; layer = 0; animationBlendMode = AnimationBlendMode.Blend; wrapMode = WrapMode.Default; } // AnimationState
/// <summary> /// Loads a series of .obj files from a folder. /// Objs must be triangulated and contain only uvs, vertices and facese. /// </summary> /// <param name="folderLocationAndName">Location + the start of the file name without the ".obj" at the end.</param> /// <param name="animationId">The key to store the animation as.</param> /// <param name="playbackSpeed">Playback speed in milliseconds perframe.</param> public void AddAnimationFolder(string folderLocationAndName, int animationId, int playbackSpeed) { int i = 0; string tmpFilename; ModelAnimation tmpAnimation = new ModelAnimation(playbackSpeed); while (File.Exists(tmpFilename = folderLocationAndName + i++.ToString() + GlobalConstants.fileFormat3D)) { tmpAnimation.AddFrameFromObj(tmpFilename); } Animations.Add(animationId, tmpAnimation); }
public WithVoxelBody(Actor self, WithVoxelBodyInfo info) : base(info) { var body = self.Trait <BodyOrientation>(); rv = self.Trait <RenderVoxels>(); var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence); modelAnimation = new ModelAnimation(model, () => WVec.Zero, () => new[] { body.QuantizeOrientation(self, self.Orientation) }, () => IsTraitDisabled, () => 0, info.ShowShadow); rv.Add(modelAnimation); }
} // ContainsAnimationClip #endregion #region Add Animation Clip /// <summary> /// Adds a clip to the animation with name newName. /// </summary> public void AddAnimationClip(ModelAnimation animation, string newName = null) { if (newName == null) { newName = animation.Name; } if (!ContainsAnimationClip(newName)) { animationStates.Add(newName, new AnimationState(animation)); } else { throw new ArgumentException("Model Animation Component: The animation " + animation.Name + " is already assigned."); } } // AddAnimationClip
// Use this for initialization void Start() { this.gameObject.animation.Play("BeeAnimRun00"); nowState = HornetAIState.Aproach; if (Player == null) { nowLine = (int)(Random.value * (DataBase.Lines.Length - 0.01f)); LineTarget = DataBase.Lines[nowLine]; Player = DataBase.Player; FaceForward = DataBase.FaceForward; nowState = HornetAIState.Appear; } IntervalTime = Time.time + 0.5f + Random.value * 0.9f; Timer = 0.0f; LMMV = 0.0f; randPos = new Vector3( (Random.value - 0.5f) * 1.7f, (Random.value - 0.2f) * 0.8f, (Random.value - 0.5f) * 1.3f ); #if false LineTarget.position = LineTarget.position + LineTarget.right * randPos.x + LineTarget.up * randPos.y + LineTarget.forward * randPos.z; #else LineTargetPos = LineTarget.position + LineTarget.right * randPos.x + LineTarget.up * randPos.y + LineTarget.forward * randPos.z; #endif burningS = this.transform.GetComponentInChildren <ObjectBurning>(); AudioSource AS = GetComponent <AudioSource>(); if (AS != null) { AS.pitch = (Random.value - 0.5f) - 0.5f; } modelAnim = this.transform.GetComponentInChildren <ModelAnimation>(); RenderMat = GetComponentInChildren <SkinnedMeshRenderer>().materials; }
public List <ModelAnimation> readAnimationsFromFile(String fileName) { StreamReader inFile = new StreamReader(fileName); //read number of animations int numOfAnimations = int.Parse(inFile.ReadLine()); List <ModelAnimation> animations = new List <ModelAnimation>(); //split animations into separate strings for (int a = 0; a < numOfAnimations; ++a) { string animationString = ""; string fileLine; bool readingFrame = false; //read all animation data into string then send to ModelAnimation to return the animation //read until you encounter an empty line while ((fileLine = inFile.ReadLine()) != "") { if (fileLine == "beginframe") { readingFrame = true; continue; } else if (fileLine == "endframe") { readingFrame = false; //ended frame, skip to next line animationString += "\n"; continue; } animationString += fileLine + (readingFrame ? "\r" : "\n"); } //send to ModelAnimation to return an animation animations.Add(ModelAnimation.deserializeAnimation(animationString, model)); animationString = ""; } //Finished creating animations from file, now assign it to our list of animations //this.animations = animations; return(animations); //return true; }
public WithVoxelAnimatedBody(Actor self, WithVoxelAnimatedBodyInfo info) : base(info) { this.info = info; var body = self.Trait <BodyOrientation>(); rv = self.Trait <RenderVoxels>(); var voxel = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence); frames = voxel.Frames; modelAnimation = new ModelAnimation(voxel, () => WVec.Zero, () => body.QuantizeOrientation(self.Orientation), () => IsTraitDisabled, () => frame, info.ShowShadow); rv.Add(modelAnimation); }
public WithVoxelWalkerBody(Actor self, WithVoxelWalkerBodyInfo info) { this.info = info; movement = self.Trait <IMove>(); var body = self.Trait <BodyOrientation>(); rv = self.Trait <RenderVoxels>(); var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence); frames = model.Frames; modelAnimation = new ModelAnimation(model, () => WVec.Zero, () => new[] { body.QuantizeOrientation(self, self.Orientation) }, () => false, () => frame, info.ShowShadow); rv.Add(modelAnimation); }
public WithVoxelUnloadBody(Actor self, WithVoxelUnloadBodyInfo info) { var body = self.Trait <BodyOrientation>(); rv = self.Trait <RenderVoxels>(); var idleModel = self.World.ModelCache.GetModelSequence(rv.Image, info.IdleSequence); modelAnimation = new ModelAnimation(idleModel, () => WVec.Zero, () => new[] { body.QuantizeOrientation(self, self.Orientation) }, () => Docked, () => 0, info.ShowShadow); rv.Add(modelAnimation); var unloadModel = self.World.ModelCache.GetModelSequence(rv.Image, info.UnloadSequence); rv.Add(new ModelAnimation(unloadModel, () => WVec.Zero, () => new[] { body.QuantizeOrientation(self, self.Orientation) }, () => !Docked, () => 0, info.ShowShadow)); }
private int[] BuildChannelMap(Model model, ModelAnimation animation) { var channelMap = new int[animation.Channels.Count]; for (int i = 0; i < animation.Channels.Count; i++) { channelMap[i] = -1; foreach (var bone in model.Bones) { if (bone.Name == animation.Channels[i].BoneName) { channelMap[i] = bone.Index; break; } } } return(channelMap); }
public static ModelAnimation deserializeAnimation(string serAnim, GameObject animModel) { ModelAnimation anim = new ModelAnimation(); Queue <string> animData = new Queue <string>(serAnim.Split('\n')); //Store animation name anim.name = animData.Dequeue(); //Store animation playback speed anim.playbackSpeed = float.Parse(animData.Dequeue()); //Create array for transform of length of number of transforms Transform [] transforms = new Transform[int.Parse(animData.Dequeue())]; //Load model transforms into transform array for (int t = 0; t < transforms.Length; ++t) { string transName = animData.Dequeue(); if (transName == animModel.transform.root.name) { transforms[t] = animModel.transform.root; } else { transforms[t] = animModel.transform.Find(transName); } } //set animation transforms anim.modelTransforms = transforms; //Next dequeue gets number of animations anim.frames = new AnimationFrame[int.Parse(animData.Dequeue())]; //Get animation frames for (int a = 0; a < anim.frames.Length; ++a) { anim.frames[a] = AnimationFrame.deserializeFrame(animData.Dequeue()); } return(anim); }
/// <summary> /// Starts a new animation. /// </summary> /// <param name="model">The animated model.</param> /// <param name="animation">The animation to play.</param> public void StartAnimation(Model model, ModelAnimation animation) { if (model == null) { throw new ArgumentNullException("model"); } if (animation == null) { throw new ArgumentNullException("animation"); } animationStates[model] = new AnimationState { Model = model, Animation = animation, ChannelMap = BuildChannelMap(model, animation) }; }
//Sets the animations playback speed as close as possible to the desired playback speed public ModelAnimation setAnimationPlaybackAsCloseAsPossible(ModelAnimation theAnimation, float pBackSpeed) { if (pBackSpeed <= 0) { Debug.Log("Resolution should be greater than 0"); return(theAnimation); } ModelAnimation equalizedAnimation = new ModelAnimation(); List <AnimationFrame> newFrameList = new List <AnimationFrame>(); float averageAnimationFrameLength = 100 / theAnimation.getAveragePlaybackSpeed(); //get closest float that divides evenly into animation length, rounds down and increases number of frames, gets better resolut float actualPbackSpeed = pBackSpeed - ((Mathf.CeilToInt(averageAnimationFrameLength) % (int)pBackSpeed) / 2); int numberOfFrames = (int)(averageAnimationFrameLength / actualPbackSpeed); //initialize animation name, transforms, playback speed, and priority equalizedAnimation.name = theAnimation.name; equalizedAnimation.modelTransforms = theAnimation.modelTransforms; equalizedAnimation.playbackSpeed = actualPbackSpeed; equalizedAnimation.priority = theAnimation.priority; //Add origin frame AnimationFrame newFrame = new AnimationFrame(equalizedAnimation.modelTransforms.Length, "Origin Frame"); newFrame.positionStates = theAnimation.frames[0].positionStates; newFrame.rotationStates = theAnimation.frames[0].rotationStates; newFrameList.Add(newFrame); for (int f = 1; f < numberOfFrames; ++f) { newFrame = new AnimationFrame(equalizedAnimation.modelTransforms.Length, "Frame " + f); newFrame.positionStates = theAnimation.getPositionsForPercentComplete((float)f / (numberOfFrames - 1)); newFrame.rotationStates = theAnimation.getRotationsForPercentComplete((float)f / (numberOfFrames - 1)); newFrameList.Add(newFrame); } equalizedAnimation.frames = newFrameList.ToArray(); return(equalizedAnimation); }
public void ClearBattleResouces() { ClickIcon.Clear(); SurfaceManager.ClearResources(); ModelAnimation.ClearData(); BaseAction.ClearResources(); this.ClearDynamicDrawerResources(); ResourceManager.ClearResources(); GameObject gameObject = GameObject.Find("SpawnerPool(Clone)"); if (gameObject != null) { PoolRoot component = gameObject.GetComponent <PoolRoot>(); if (component != null) { component.ClearResources(); } } this.ClearBattleSceneResources(false); Resources.UnloadUnusedAssets(); }
public static void Stop(GameObject gm, MeshAnimation[] tma, string res, string name) { if (gm.animation.enabled) { return; } ModelAnimation.m_AnimationInfo = ModelAnimation.GetAnimationInfo(res + "/" + name); if (ModelAnimation.m_AnimationInfo == null) { return; } ModelAnimation.m_WarpMode = WrapMode.Once; ModelAnimation.m_fSpeed = 1.2f; ModelAnimation.m_iEventPostIndex = -1; int num = 1000; ModelAnimation.m_fCurPlayTime = (float)num * (1f / (float)ModelAnimation.m_AnimationInfo.iFrameRate); for (int i = 0; i < tma.Length; i++) { tma[i].PlayAnimation(res, name, ModelAnimation.m_AnimationInfo.iFrameRate, ModelAnimation.m_WarpMode, ModelAnimation.m_fSpeed, num); } }
//equalize animations and add or remove frames so that each frame takes the same number of cycles public ModelAnimation equalizeAnimation(ModelAnimation theAnimation, int resolution = 1) { if (resolution <= 0) { Debug.Log("Resolution should be greater than 0"); return(theAnimation); } ModelAnimation equalizedAnimation = new ModelAnimation(); List <AnimationFrame> newFrameList = new List <AnimationFrame>(); //initialize animation name, transforms, playback speed, and priority equalizedAnimation.name = theAnimation.name; equalizedAnimation.modelTransforms = theAnimation.modelTransforms; equalizedAnimation.playbackSpeed = theAnimation.getAveragePlaybackSpeed() * resolution; equalizedAnimation.priority = theAnimation.priority; int numberOfFrames = theAnimation.frames.Length * resolution; //Add origin frame AnimationFrame newFrame = new AnimationFrame(equalizedAnimation.modelTransforms.Length, "Origin Frame"); newFrame.positionStates = theAnimation.frames[0].positionStates; newFrame.rotationStates = theAnimation.frames[0].rotationStates; newFrameList.Add(newFrame); for (int f = 1; f < numberOfFrames; ++f) { newFrame = new AnimationFrame(equalizedAnimation.modelTransforms.Length, "Frame " + f); newFrame.positionStates = theAnimation.getPositionsForPercentComplete((float)f / (numberOfFrames - 1)); newFrame.rotationStates = theAnimation.getRotationsForPercentComplete((float)f / (numberOfFrames - 1)); newFrameList.Add(newFrame); } equalizedAnimation.frames = newFrameList.ToArray(); return(equalizedAnimation); }
private void DrawTriangle(Vector3 tmpVertex1, Vector3 tmpVertex2, Vector3 tmpVertex3, ModelAnimation mod, Camara cam) { //set array boundes int left = (int)Math.Max(0, Left(tmpVertex1, tmpVertex2, tmpVertex3)); int right = (int)Math.Min(cam.GetScreenWidth(), Right(tmpVertex1, tmpVertex2, tmpVertex3)); int top = (int)Math.Max(0, Top(tmpVertex1, tmpVertex2, tmpVertex3)); int bottom = (int)Math.Min(cam.GetScreenWidth(), Bottom(tmpVertex1, tmpVertex2, tmpVertex3)); //setup values for the draw loop int x1 = (int)tmpVertex1.x; int y1 = (int)tmpVertex1.y; float z1 = tmpVertex1.z; int x2 = (int)tmpVertex2.x; int y2 = (int)tmpVertex2.y; float z2 = tmpVertex2.z; int x3 = (int)tmpVertex3.x; int y3 = (int)tmpVertex3.y; float z3 = tmpVertex3.z; //percomputer values float totalArea = -Area(tmpVertex1, tmpVertex2, tmpVertex3); int y2my3 = y2 - y3; int y3my1 = y3 - y1; int y1my2 = y1 - y2; //computing uvs float uvX1 = Uv1.u * mod.GetTextureWidth(); float uvX2 = Uv2.u * mod.GetTextureWidth(); float uvX3 = Uv3.u * mod.GetTextureWidth(); float uvY1 = Uv1.v * mod.GetTextureHeight(); float uvY2 = Uv2.v * mod.GetTextureHeight(); float uvY3 = Uv3.v * mod.GetTextureHeight(); //draw loop for (int y = top; y < bottom; y++) { int apre = x2 * (y3 - y) + x3 * (y - y2); int bpre = x1 * (y - y3) + x3 * (y1 - y); int cpre = x1 * (y2 - y) + x2 * (y - y1); for (int x = left; x < right; x++) { float ba = Math.Abs(x * y2my3 + apre) / totalArea; float bb = Math.Abs(x * y3my1 + bpre) / totalArea; float bc = Math.Abs(x * y1my2 + cpre) / totalArea; //test if point is in triangle if (ba + bb + bc <= totalArea) { //get the uv/depth int u = (int)(uvY1 * ba + uvY2 * bb + uvY3 * bc); int v = (int)(uvX1 * ba + uvX2 * bb + uvX3 * bc); float depth = z1 * ba + z2 * bb + z3 * bc; //set the pixel if passes depth test cam.screen[x, y].PixelSetDepthTest(mod.texture[u, v], depth); } } } }
public ModelAnimation mergeAnimations(ModelAnimation[] modelAnimations) { if (modelAnimations.Length == 1) { return(modelAnimations[0]); } ModelAnimation mergedAnimation = new ModelAnimation(); //sort animations by priority then by longest length modelAnimations = modelAnimations.OrderBy(si => si.priority).ToArray(); //reverse so it's ordered by descending priority Array.Reverse(modelAnimations); List <ModelAnimation> intermedAnimList = new List <ModelAnimation>(); intermedAnimList.Add(modelAnimations[0]); int thePriority = modelAnimations[0].priority; //Now sort each priority level by total animation cycles List <ModelAnimation> tempAnimList = new List <ModelAnimation>(); for (int a = 1; a < modelAnimations.Length; ++a) { if (modelAnimations[a].priority == thePriority) { intermedAnimList.Add(modelAnimations[a]); } else { tempAnimList.AddRange(intermedAnimList.OrderBy(si => si.getTotalCyclesInAnimation()).Reverse()); intermedAnimList.Clear(); intermedAnimList.Add(modelAnimations[a]); } } tempAnimList.AddRange(intermedAnimList.OrderBy(si => si.getTotalCyclesInAnimation()).Reverse()); modelAnimations = tempAnimList.ToArray(); //Done sorting //equalize all animations to make it easier to merge them for (int a = 0; a < modelAnimations.Length; ++a) { modelAnimations[a] = setAnimationPlaybackAsCloseAsPossible(modelAnimations[a], 4); } //Base the length of the merged animation off of the largest one with the highest priority //If no guide animation was sent into the function ModelAnimation guideAnimation = modelAnimations[0]; List <Transform> allTransforms = new List <Transform>(); List <AnimationFrame> allFrames = new List <AnimationFrame>(); //for each frame build a new merged frame for (int f = 0; f < guideAnimation.frames.Length; ++f) { List <Transform> usedTransforms = new List <Transform>(); List <Vector3> positions = new List <Vector3>(); List <Quaternion> rotations = new List <Quaternion>(); //for each animation to merge for (int a = 0; a < modelAnimations.Length; ++a) { //if it's transform hasn't been used this frame then use it because the animations are already sorted in order of usage for (int t = 0; t < modelAnimations[a].modelTransforms.Length; ++t) { if (!usedTransforms.Contains(modelAnimations[a].modelTransforms[t])) { //If new animation frame number has gone beyong this animation's last frame number, then it no longer contributes if (modelAnimations[a].frames.Length <= f) { positions.Add(modelAnimations[a].frames[modelAnimations[a].frames.Length - 1].positionStates[t]); rotations.Add(modelAnimations[a].frames[modelAnimations[a].frames.Length - 1].rotationStates[t]); } else { positions.Add(modelAnimations[a].frames[f].positionStates[t]); rotations.Add(modelAnimations[a].frames[f].rotationStates[t]); } usedTransforms.Add(modelAnimations[a].modelTransforms[t]); if (!allTransforms.Contains(modelAnimations[a].modelTransforms[t])) { allTransforms.Add(modelAnimations[a].modelTransforms[t]); } } } } allFrames.Add(new AnimationFrame("Frame " + f, positions.ToArray(), rotations.ToArray())); } string aniName = ""; foreach (ModelAnimation ani in modelAnimations) { aniName += ani.name + "-"; } mergedAnimation.name = aniName + "Merged"; mergedAnimation.playbackSpeed = guideAnimation.playbackSpeed; mergedAnimation.modelTransforms = allTransforms.ToArray(); mergedAnimation.frames = allFrames.ToArray(); //make last frame a return to origin frame (maybe) return(mergedAnimation); }
public AnimationWrapper(ModelAnimation model) { this.model = model; }
public void Add(ModelAnimation ma) { components.Add(ma); wrappers.Add(ma, new AnimationWrapper(ma)); }
public void Remove(ModelAnimation m) { components.Remove(m); wrappers.Remove(m); }
public ModelAnimation stringAnimationsForNewAnimation(ModelAnimation[] modelAnimations, float[] pauses, bool skipOriginFrame, bool skipTheBackToOriginFrame) { ModelAnimation strungAnimation = new ModelAnimation(); List <Transform> allTransforms = new List <Transform>(); List <AnimationFrame> allFrames = new List <AnimationFrame>(); AnimationFrame newFrame; string theName = ""; //get transforms for all animations and initialize strungAnimation foreach (ModelAnimation ani in modelAnimations) { theName += ani.name + "-"; foreach (Transform t in ani.modelTransforms) { if (!(allTransforms.Contains(t))) { allTransforms.Add(t); } } } strungAnimation.name = theName + "String"; strungAnimation.modelTransforms = allTransforms.ToArray(); strungAnimation.playbackSpeed = 1; strungAnimation.priority = 0; //for each animation... for (int a = 0; a < modelAnimations.Length; ++a) { //Put this animation's transformsinto a list for easy checking List <Transform> thisAnimationTransforms = modelAnimations[a].modelTransforms.ToList(); //for each frame... for (int f = (a > 0 && skipOriginFrame ? 1 : 0); f < modelAnimations[a].frames.Length + (skipTheBackToOriginFrame ? -1 : 0); ++f) { newFrame = new AnimationFrame(allTransforms.Count, "Frame " + allFrames.Count); newFrame.playbackSpeed = modelAnimations[a].frames[f].playbackSpeed == 0 ? 0 : modelAnimations[a].frames[f].playbackSpeed; //for each transform... for (int t = 0; t < allTransforms.Count; ++t) { //if current animation contains this transform if (thisAnimationTransforms.Contains(allTransforms[t])) { //set position and rotation for this frame newFrame.positionStates[t] = modelAnimations[a].frames[f].positionStates[thisAnimationTransforms.IndexOf(allTransforms[t])]; newFrame.rotationStates[t] = modelAnimations[a].frames[f].rotationStates[thisAnimationTransforms.IndexOf(allTransforms[t])]; } else { //else set position and rotation for this transform to the same position and rotation as last frame //If this is the first frame and you reach a transform not used in this animation... if (allFrames.Count == 0) { //Check each animation after the first one to see if the transform is contained in it //if it is then use that animations first frame position state for this position state, same for rotation for (int an = 1; an < modelAnimations.Length; ++an) { List <Transform> otherAnimationTransforms = modelAnimations[an].modelTransforms.ToList(); if (otherAnimationTransforms.Contains(allTransforms[t])) { newFrame.positionStates[t] = modelAnimations[an].frames[0].positionStates[otherAnimationTransforms.IndexOf(allTransforms[t])]; newFrame.rotationStates[t] = modelAnimations[an].frames[0].rotationStates[otherAnimationTransforms.IndexOf(allTransforms[t])]; break; } } } else { newFrame.positionStates[t] = allFrames[allFrames.Count - 1].positionStates[t]; newFrame.rotationStates[t] = allFrames[allFrames.Count - 1].rotationStates[t]; } } } //add frame to allFrames allFrames.Add(newFrame); } //Add the pause if there is one if (a < pauses.Length) { newFrame = new AnimationFrame(allTransforms.Count, "Frame " + allFrames.Count); newFrame.playbackSpeed = (100 / pauses[a]) * 0.0025F; //Set position and rotation equal to position and rotation of last frame newFrame.positionStates = allFrames[allFrames.Count - 1].positionStates; newFrame.rotationStates = allFrames[allFrames.Count - 1].rotationStates; allFrames.Add(newFrame); } } //Finalize strung animations strungAnimation.frames = allFrames.ToArray(); //equalize the animation //strungAnimation = equalizeAnimation(strungAnimation, 3); return(strungAnimation); }
private void ApplyAnimation_Click_Model() { var xml = XDocument.Parse(txt.Text); var es = xml.Root.Elements().ToList(); ModelAnimation = new List <ModelAnimation>(); for (int i = 0; i < es.Count(); i++) { var anim = new ModelAnimation(); var ats = es[i].Attributes().ToList(); var transformkeydata2 = new TransformKeyData2 { TransformKey = new TransformKey() }; anim.Name = ats[1].Value; transformkeydata2.Duration = TimeSpan.FromMilliseconds(double.Parse(ats[2].Value)); var inits = es[i].Elements().ToList()[0].Elements().ToList(); if (inits.Count != 0) { transformkeydata2.TransformKey.Translation = new Vector3( float.Parse(inits[0].Attribute("X").Value), float.Parse(inits[0].Attribute("Y").Value), float.Parse(inits[0].Attribute("Z").Value) ); transformkeydata2.TransformKey.Rotation = new Vector3( float.Parse(inits[1].Attribute("X").Value), float.Parse(inits[1].Attribute("Y").Value), float.Parse(inits[1].Attribute("Z").Value) ).ToQuaternion(); transformkeydata2.TransformKey.Scale = new Vector3( float.Parse(inits[2].Attribute("X").Value), float.Parse(inits[2].Attribute("Y").Value), float.Parse(inits[2].Attribute("Z").Value) ); var transformkey = es[i].Elements().ToList()[1].Elements(); var translationkey = transformkey.Where(_ => _.Name == "translation_key").ToList(); for (int j = 0; j < translationkey.Count(); j++) { transformkeydata2.TransformKey.TKey.Add(new TKey { Duration = TimeSpan.FromMilliseconds(double.Parse(translationkey[j].Attribute("tick_time").Value)), Translation = new Vector3( float.Parse(translationkey[j].Attribute("X").Value), float.Parse(translationkey[j].Attribute("Y").Value), float.Parse(translationkey[j].Attribute("Z").Value) ) }); } var rotationkey = transformkey.Where(_ => _.Name == "rotation_key").ToList(); for (int k = 0; k < rotationkey.Count(); k++) { transformkeydata2.TransformKey.RKey.Add(new RKey { Duration = TimeSpan.FromMilliseconds(double.Parse(rotationkey[k].Attribute("tick_time").Value)), Rotation = new Vector3( float.Parse(rotationkey[k].Attribute("X").Value), float.Parse(rotationkey[k].Attribute("Y").Value), float.Parse(rotationkey[k].Attribute("Z").Value) ).ToQuaternion() }); } var scalekey = transformkey.Where(_ => _.Name == "scale_key").ToList(); for (int l = 0; l < scalekey.Count(); l++) { transformkeydata2.TransformKey.SKey.Add(new SKey { Duration = TimeSpan.FromMilliseconds(double.Parse(scalekey[l].Attribute("tick_time").Value)), Scale = new Vector3( float.Parse(scalekey[l].Attribute("X").Value), float.Parse(scalekey[l].Attribute("Y").Value), float.Parse(scalekey[l].Attribute("Z").Value) ) }); } } var floatkey = es[i].Elements().ToList()[2].Elements().ToList(); for (int m = 0; m < floatkey.Count(); m++) { transformkeydata2.FloatKeys.Add(new FloatKey { Duration = TimeSpan.FromMilliseconds(double.Parse(floatkey[m].Attribute("tick_time").Value)), Alpha = float.Parse(floatkey[m].Attribute("alpha").Value) }); } var morphkey = es[i].Elements().ToList()[3].Elements().ToList(); for (int n = 0; n < morphkey.Count(); n++) { var m = new MorphKey { Duration = TimeSpan.FromMilliseconds(double.Parse(morphkey[n].Attribute("tick_time").Value)) }; var mpl = new List <Vector3>(); var mp = morphkey[n].Elements().Where(_ => _.Name == "morph_position").ToList(); for (int o = 0; o < mp.Count; o++) { mpl.Add(new Vector3( float.Parse(mp[o].Attribute("X").Value), float.Parse(mp[o].Attribute("Y").Value), float.Parse(mp[o].Attribute("Z").Value))); } m.Positions = mpl; var mrl = new List <Quaternion>(); var mr = morphkey[n].Elements().Where(_ => _.Name == "morph_rotation").ToList(); for (int p = 0; p < mr.Count; p++) { mrl.Add(new Vector3( float.Parse(mr[p].Attribute("X").Value), float.Parse(mr[p].Attribute("Y").Value), float.Parse(mr[p].Attribute("Z").Value)).ToQuaternion()); } m.Rotations = mrl; transformkeydata2.MorphKeys.Add(m); } anim.TransformKeyData2 = transformkeydata2; ModelAnimation.Add(anim); } }
public override void PrepareRenderables() { var voxel = GetVoxel(); var palette = GetPalette(); var playerPalette = GetPlayerPalette(); var normalsPalette = GetNormalsPalette(); var shadowPalette = GetShadowPalette(); var scale = GetScale(); var rotation = GetRotation(); var lightAmbientColor = GetLightAmbientColor(); var lightDiffuseColor = GetLightDiffuseColor(); var lightPitch = GetLightPitch(); var lightYaw = GetLightYaw(); var cameraAngle = GetCameraAngle(); if (voxel == null || palette == null) { return; } if (voxel != cachedVoxel) { cachedVoxel = voxel; } if (palette != cachedPalette) { if (string.IsNullOrEmpty(palette) && string.IsNullOrEmpty(playerPalette)) { return; } var paletteName = string.IsNullOrEmpty(palette) ? playerPalette : palette; paletteReference = WorldRenderer.Palette(paletteName); cachedPalette = paletteName; } if (playerPalette != cachedPlayerPalette) { paletteReferencePlayer = WorldRenderer.Palette(playerPalette); cachedPlayerPalette = playerPalette; } if (normalsPalette != cachedNormalsPalette) { paletteReferenceNormals = WorldRenderer.Palette(normalsPalette); cachedNormalsPalette = normalsPalette; } if (shadowPalette != cachedShadowPalette) { paletteReferenceShadow = WorldRenderer.Palette(shadowPalette); cachedShadowPalette = shadowPalette; } if (scale != cachedScale) { cachedScale = scale; } if (rotation != cachedRotation) { cachedRotation = rotation; } if (lightPitch != cachedLightPitch) { cachedLightPitch = lightPitch; } if (lightYaw != cachedLightYaw) { cachedLightYaw = lightYaw; } if (cachedLightAmbientColor[0] != lightAmbientColor[0] || cachedLightAmbientColor[1] != lightAmbientColor[1] || cachedLightAmbientColor[2] != lightAmbientColor[2]) { cachedLightAmbientColor = lightAmbientColor; } if (cachedLightDiffuseColor[0] != lightDiffuseColor[0] || cachedLightDiffuseColor[1] != lightDiffuseColor[1] || cachedLightDiffuseColor[2] != lightDiffuseColor[2]) { cachedLightDiffuseColor = lightDiffuseColor; } if (cameraAngle != cachedCameraAngle) { cachedCameraAngle = cameraAngle; } if (cachedVoxel == null) { return; } var animation = new ModelAnimation( cachedVoxel, () => WVec.Zero, () => cachedRotation, () => false, () => 0, true); var animations = new ModelAnimation[] { animation }; ModelPreview preview = new ModelPreview( new ModelAnimation[] { animation }, WVec.Zero, 0, cachedScale, new WAngle(cachedLightPitch), new WAngle(cachedLightYaw), cachedLightAmbientColor, cachedLightDiffuseColor, cachedCameraAngle, paletteReference, paletteReferenceNormals, paletteReferenceShadow); var screenBounds = animation.ScreenBounds(WPos.Zero, WorldRenderer, scale); IdealPreviewSize = new int2(screenBounds.Width, screenBounds.Height); var origin = RenderOrigin + new int2(RenderBounds.Size.Width / 2, RenderBounds.Size.Height / 2); var camera = new WRot(WAngle.Zero, cachedCameraAngle - new WAngle(256), new WAngle(256)); var modelRenderable = new UIModelRenderable( animations, WPos.Zero, origin, 0, camera, scale, WRot.None, cachedLightAmbientColor, cachedLightDiffuseColor, paletteReferencePlayer, paletteReferenceNormals, paletteReferenceShadow); renderable = modelRenderable.PrepareRender(WorldRenderer); }
/// <summary> /// Load the resources. /// </summary> /// <remarks>Remember to call the base implementation of this method.</remarks> protected override void LoadContent() { #region Setup Input Controls buttons = new Button[4]; // Create the virtual buttons to control the scene selection. buttons[0] = new Button { Name = "Attack", ButtonBehavior = Button.ButtonBehaviors.DigitalInput, KeyButton = new KeyButton(Keys.Space), }; buttons[1] = new Button { Name = "Attack", ButtonBehavior = Button.ButtonBehaviors.DigitalInput, KeyButton = new KeyButton(Buttons.RightTrigger), }; axis = new Axis { Name = "Walk", AnalogAxis = AnalogAxes.LeftStickY, AxisBehavior = Axis.AxisBehaviors.AnalogInput, }; buttons[2] = new Button { Name = "WalkPC", KeyButton = new KeyButton(Keys.W), ButtonBehavior = Button.ButtonBehaviors.DigitalInput }; buttons[3] = new Button { Name = "RunPC", KeyButton = new KeyButton(Keys.LeftShift), ButtonBehavior = Button.ButtonBehaviors.DigitalInput }; #endregion #region Camera camera = new GameObject3D(); camera.AddComponent <Camera>(); camera.AddComponent <SoundListener>(); camera.Camera.RenderTargetSize = Size.FullScreen; camera.Camera.FarPlane = 100; camera.Camera.NearPlane = 1f; camera.Transform.LookAt(new Vector3(-10, 10, 20), new Vector3(0, 5, 0), Vector3.Up); //ScriptCustomCameraScript script = (ScriptCustomCameraScript)camera.AddComponent<ScriptCustomCameraScript>(); //script.SetPosition(new Vector3(0, 10, 20), new Vector3(0, 5, 0)); camera.Camera.ClearColor = Color.Black; camera.Camera.FieldOfView = 180 / 6f; camera.Camera.PostProcess = new PostProcess(); camera.Camera.PostProcess.ToneMapping.AutoExposureEnabled = true; camera.Camera.PostProcess.MLAA.Enabled = true; camera.Camera.PostProcess.MLAA.EdgeDetection = MLAA.EdgeDetectionType.Color; camera.Camera.PostProcess.Bloom.Threshold = 3.5f; camera.Camera.AmbientLight = new AmbientLight { SphericalHarmonicLighting = SphericalHarmonicL2.GenerateSphericalHarmonicFromCubeTexture(new TextureCube("FactoryCatwalkRGBM") { IsRgbm = true, RgbmMaxRange = 50, }), Color = new Color(10, 10, 10), Intensity = 5f, }; //camera.Camera.Sky = new Skybox { TextureCube = new TextureCube("FactoryCatwalkRGBM") { IsRgbm = true, RgbmMaxRange = 50, } }; #endregion #region Models dude = new GameObject3D(new FileModel("DudeWalk"), new BlinnPhong()); // One material for mesh part. dude.ModelRenderer.MeshMaterials = new Material[5]; dude.ModelRenderer.MeshMaterials[0] = new BlinnPhong { DiffuseTexture = new Texture("Dude\\head"), NormalTexture = new Texture("Dude\\headN"), SpecularTexture = new Texture("Dude\\headS"), SpecularPowerFromTexture = false, SpecularPower = 300 }; dude.ModelRenderer.MeshMaterials[2] = new BlinnPhong { DiffuseTexture = new Texture("Dude\\jacket"), NormalTexture = new Texture("Dude\\jacketN"), SpecularTexture = new Texture("Dude\\jacketS"), SpecularPowerFromTexture = false, SpecularPower = 300 }; dude.ModelRenderer.MeshMaterials[3] = new BlinnPhong { DiffuseTexture = new Texture("Dude\\pants"), NormalTexture = new Texture("Dude\\pantsN"), SpecularTexture = new Texture("Dude\\pantsS"), SpecularPowerFromTexture = false, SpecularPower = 300 }; dude.ModelRenderer.MeshMaterials[1] = new BlinnPhong { DiffuseTexture = new Texture("Dude\\upBodyC"), NormalTexture = new Texture("Dude\\upbodyN"), SpecularTexture = new Texture("Dude\\upbodyCS"), SpecularPowerFromTexture = false, SpecularPower = 300 }; dude.ModelRenderer.MeshMaterials[4] = new BlinnPhong { DiffuseTexture = new Texture("Dude\\upBodyC"), NormalTexture = new Texture("Dude\\upbodyN"), SpecularTexture = new Texture("Dude\\upbodyCS"), SpecularPowerFromTexture = false, SpecularPower = 300 }; dude.Transform.LocalScale = new Vector3(0.1f, 0.1f, 0.1f); // Add animations. dude.AddComponent <ModelAnimations>(); ModelAnimation modelAnimation; // First DudeAttack. #if XBOX modelAnimation = new ModelAnimation("DudeAttackXbox"); // Be aware to select the correct content processor when you add your fbx files on the solution. modelAnimation.WrapMode = WrapMode.ClampForever; dude.ModelAnimations.AddAnimationClip(modelAnimation); #else modelAnimation = new ModelAnimation("DudeAttack"); // Be aware to select the correct content processor when you add your fbx files on the solution. modelAnimation.WrapMode = WrapMode.ClampForever; dude.ModelAnimations.AddAnimationClip(modelAnimation); #endif // Then DudeRun. #if XBOX modelAnimation = new ModelAnimation("DudeRunXbox"); // Be aware to select the correct content processor when you add your fbx files on the solution. modelAnimation.WrapMode = WrapMode.Loop; dude.ModelAnimations.AddAnimationClip(modelAnimation); #else modelAnimation = new ModelAnimation("DudeRun"); // Be aware to select the correct content processor when you add your fbx files on the solution. modelAnimation.WrapMode = WrapMode.Loop; dude.ModelAnimations.AddAnimationClip(modelAnimation); #endif // Set the parameters from the animation that it is stored in DudeWalk (this animation is added automatically by the system). dude.ModelAnimations["Take 001"].WrapMode = WrapMode.Loop; // Load the rifle model. rifle = new GameObject3D(new FileModel("Rifle"), new BlinnPhong { DiffuseColor = new Color(15, 15, 15), SpecularPower = 100, SpecularIntensity = 0.01f }); // And a floor floor = new GameObject3D(new FileModel("Terrain/TerrainLOD0Grid"), new BlinnPhong { SpecularPower = 300, DiffuseColor = new Color(250, 250, 250), SpecularIntensity = 0.0f, }) { Transform = { LocalScale = new Vector3(5, 5, 5) } }; #endregion #region Shadows and Lights Shadow.DistributeShadowCalculationsBetweenFrames = true; directionalLight = new GameObject3D(); directionalLight.AddComponent <DirectionalLight>(); directionalLight.DirectionalLight.Color = new Color(250, 250, 140); directionalLight.DirectionalLight.Intensity = 25f; directionalLight.Transform.LookAt(new Vector3(-0.75f, 0.85f, -1.3f), Vector3.Zero, Vector3.Forward); directionalLight.DirectionalLight.Shadow = new CascadedShadow { Filter = Shadow.FilterType.PcfPosion, LightDepthTextureSize = Size.Square1024X1024, }; DirectionalLight.Sun = directionalLight.DirectionalLight; #endregion #region Dog Fight Studios // Dog Fight Studios share their animations and the scene logic. GameObject2D dogFightStudios = new GameObject2D(); dogFightStudios.AddComponent <HudTexture>(); dogFightStudios.HudTexture.Texture = new Texture("DogFightStudios"); dogFightStudios.Transform.Position = new Vector3(-55, -80, 0); #endregion } // Load
/// <summary> /// モデルのファイルパス /// </summary> /// <param name="modelType"></param> /// <param name="modelColor"></param> /// <param name="modelAnimation"></param> /// <returns></returns> public static String GetModelPath(ModelType modelType, ModelColor modelColor, ModelAnimation modelAnimation) { String filePath = DirBWave; switch (modelType) { case ModelType.Metall: switch (modelColor) { case ModelColor.BLUE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirBMetallN; case ModelAnimation.WALK: return DirBMetallW; case ModelAnimation.ATTACK: return DirBMetallA; } break; case ModelColor.RED: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirRMetallN; case ModelAnimation.WALK: return DirRMetallW; case ModelAnimation.ATTACK: return DirRMetallA; } break; case ModelColor.GREEN: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirGMetallN; case ModelAnimation.WALK: return DirGMetallW; case ModelAnimation.ATTACK: return DirGMetallA; } break; case ModelColor.ORANGE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirOMetallN; case ModelAnimation.WALK: return DirOMetallW; case ModelAnimation.ATTACK: return DirOMetallA; } break; } break; case ModelType.Legend: switch (modelColor) { case ModelColor.BLUE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirBLegendN; case ModelAnimation.WALK: return DirBLegendW; case ModelAnimation.ATTACK: return DirBLegendA; } break; case ModelColor.RED: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirRLegendN; case ModelAnimation.WALK: return DirRLegendW; case ModelAnimation.ATTACK: return DirRLegendA; } break; case ModelColor.GREEN: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirGLegendN; case ModelAnimation.WALK: return DirGLegendW; case ModelAnimation.ATTACK: return DirGLegendA; } break; case ModelColor.ORANGE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirOLegendN; case ModelAnimation.WALK: return DirOLegendW; case ModelAnimation.ATTACK: return DirOLegendA; } break; } break; case ModelType.SnowMan: switch (modelColor) { case ModelColor.BLUE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirBSnowManN; case ModelAnimation.WALK: return DirBSnowManW; case ModelAnimation.ATTACK: return DirBSnowManA; } break; case ModelColor.RED: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirRSnowManN; case ModelAnimation.WALK: return DirRSnowManW; case ModelAnimation.ATTACK: return DirRSnowManA; } break; case ModelColor.GREEN: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirGSnowManN; case ModelAnimation.WALK: return DirGSnowManW; case ModelAnimation.ATTACK: return DirGSnowManA; } break; case ModelColor.ORANGE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirOSnowManN; case ModelAnimation.WALK: return DirOSnowManW; case ModelAnimation.ATTACK: return DirOSnowManA; } break; } break; case ModelType.Inoshishi: switch (modelColor) { case ModelColor.BLUE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirBInoshishiN; case ModelAnimation.WALK: return DirBInoshishiW; case ModelAnimation.ATTACK: return DirBInoshishiA; } break; case ModelColor.RED: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirRInoshishiN; case ModelAnimation.WALK: return DirRInoshishiW; case ModelAnimation.ATTACK: return DirRInoshishiA; } break; case ModelColor.GREEN: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirGInoshishiN; case ModelAnimation.WALK: return DirGInoshishiW; case ModelAnimation.ATTACK: return DirGInoshishiA; } break; case ModelColor.ORANGE: switch (modelAnimation) { case ModelAnimation.NORMAL: return DirOInoshishiN; case ModelAnimation.WALK: return DirOInoshishiW; case ModelAnimation.ATTACK: return DirOInoshishiA; } break; } break; case ModelType.Wave: switch (modelColor) { case ModelColor.BLUE: return DirBWave; case ModelColor.RED: return DirRWave;; case ModelColor.GREEN: return DirGWave; case ModelColor.ORANGE: return DirOWave; } break; } return DirBWave; }
public override void PrepareRenderables() { var voxel = GetVoxel(); var palette = GetPalette(); var playerPalette = GetPlayerPalette(); var normalsPalette = GetNormalsPalette(); var shadowPalette = GetShadowPalette(); var scale = GetScale(); var lightAmbientColor = GetLightAmbientColor(); var lightDiffuseColor = GetLightDiffuseColor(); var lightPitch = GetLightPitch(); var lightYaw = GetLightYaw(); if (voxel == null || palette == null) { return; } if (voxel != cachedVoxel) { offset = 0.5f * (new float2(RenderBounds.Size) - new float2(voxel.Size[0], voxel.Size[1])); cachedVoxel = voxel; } if (palette != cachedPalette) { if (string.IsNullOrEmpty(palette) && string.IsNullOrEmpty(playerPalette)) { return; } string paletteName = string.IsNullOrEmpty(palette) ? playerPalette : palette; pr = WorldRenderer.Palette(paletteName); cachedPalette = paletteName; } if (playerPalette != cachedPlayerPalette) { prPlayer = WorldRenderer.Palette(playerPalette); cachedPlayerPalette = playerPalette; } if (normalsPalette != cachedNormalsPalette) { prNormals = WorldRenderer.Palette(normalsPalette); cachedNormalsPalette = normalsPalette; } if (shadowPalette != cachedShadowPalette) { prShadow = WorldRenderer.Palette(shadowPalette); cachedShadowPalette = shadowPalette; } if (scale != cachedScale) { //offset *= scale; cachedScale = scale; } if (lightPitch != cachedLightPitch) { cachedLightPitch = lightPitch; } if (lightYaw != cachedLightYaw) { cachedLightYaw = lightYaw; } if (cachedLightAmbientColor[0] != lightAmbientColor[0] || cachedLightAmbientColor[1] != lightAmbientColor[1] || cachedLightAmbientColor[2] != lightAmbientColor[2]) { cachedLightAmbientColor = lightAmbientColor; } if (cachedLightDiffuseColor[0] != lightDiffuseColor[0] || cachedLightDiffuseColor[1] != lightDiffuseColor[1] || cachedLightDiffuseColor[2] != lightDiffuseColor[2]) { cachedLightDiffuseColor = lightDiffuseColor; } if (cachedVoxel == null) { return; } var size = new float2(cachedVoxel.Size[0] * cachedScale, cachedVoxel.Size[1] * cachedScale); ModelAnimation animation = new ModelAnimation( cachedVoxel, () => WVec.Zero, () => new List <WRot>() { new WRot( new WAngle(-45), new WAngle(-30), new WAngle(360) ) }, () => false, () => 0, true); ModelPreview preview = new ModelPreview( new ModelAnimation[] { animation }, WVec.Zero, 0, cachedScale, new WAngle(cachedLightPitch), new WAngle(cachedLightYaw), cachedLightAmbientColor, cachedLightDiffuseColor, new WAngle(), pr, prNormals, prShadow); List <ModelPreview> previews = new List <ModelPreview>() { preview }; // Calculate the preview bounds PreviewOffset = int2.Zero; IdealPreviewSize = int2.Zero; var rs = previews.SelectMany(p => ((IActorPreview)p).ScreenBounds(WorldRenderer, WPos.Zero)); if (rs.Any()) { var b = rs.First(); foreach (var rr in rs.Skip(1)) { b = OpenRA.Primitives.Rectangle.Union(b, rr); } IdealPreviewSize = new int2(b.Width, b.Height); PreviewOffset = -new int2(b.Left, b.Top) - IdealPreviewSize / 2; } renderables = previews .SelectMany(p => ((IActorPreview)p).Render(WorldRenderer, WPos.Zero)) .OrderBy(WorldRenderer.RenderableScreenZPositionComparisonKey) .Select(r => r.PrepareRender(WorldRenderer)) .ToArray(); }