protected override void Initialise()
		{
			Camera2D camera = new Camera2D();
			
			//create the draw target.
			drawToScreen = new DrawTargetScreen(camera);
			drawToScreen.ClearBuffer.ClearColour = Color.Black;


			// uncomment this to force theparticle system to run on the CPU
			// Note: This property is not available on the xbox.

			//ParticleSystem.ForceUseCpuParticleSystem = true;

			// Use ParticleSystem.SystemSupportsGpuParticles to determine if the particle
			// system will be run on the GPU
			//
			// NOTE: When running on the GPU, the particle system will be processed in 16bit floating point
			// The CPU particle system is not supported on the Xbox.



			//NEW CODE
			//create the particle system
			this.particles = new ParticleSystem(this.UpdateManager);

			//Like ModelInstance, the ParticleSystem content must be assigned before it can be drawn

			//create the particle drawer,
			//In this case, use a VelocityBillboardParticles2DElement.
			//This is a special particle drawer that will 'stretch' particles in the direction they are
			//travelling - giving them a streaky look.
			//
			particleDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles2DElement(this.particles, true);
			
			//align the drawer to the bottom centre of the screen
			particleDrawer.VerticalAlignment = VerticalAlignment.Bottom;
			particleDrawer.HorizontalAlignment = HorizontalAlignment.Centre;

			//add it to ths screen
			drawToScreen.Add(particleDrawer);
		}
        public HandController(Camera camera, Scene scene, ContentState state)
        {
            this.camera = camera;

            hand = ObjectComposer.Compose(scene, state)
                .AppendName("hand")
                .AppendMesh("hand")
                .AppendMaterialTextures("hand_map", "hand_map")
                .AppendWorld(Vector3.Zero,Vector3.Zero, Vector3.One * 0.02f)
                .AppendDummyCollider()
                .FinishAndAddToScene();

            int animationIndex = hand.Model.GetAnimationController().AnimationIndex("Take 001");
            hand.Model.GetAnimationController().PlayLoopingAnimation(animationIndex);

            bonesController = new HandAnimator(hand.Model.ModelData);
            hand.BoneModifier = bonesController;

            curseParticles = new ParticleSystem(state.Application.UpdateManager);
            TestScene._instance.AddDrawable(new BillboardParticles3D(curseParticles));
            curseParticles.ParticleSystemData = TestScene._instance.state.Load<ParticleSystemData>("Particles/Spark");
            curseParticlesTriger = curseParticles.GetTriggerByName("burst");

        }
		//the logic to emit a single particle
		public void Emit(ParticleSystem system, ParticleSystemEmitData emit, int sourceIndex, float sourceIndexF, int step)
		{
			//need more capacity?
			if (particleCapacity == particles.Length)
				Array.Resize(ref this.particles, this.particles.Length * 2);
			uint index = particleCapacity++;

			//for profiling
			maxParticleCapacity = Math.Max(maxParticleCapacity, index);

			//find the step the particle will be removed on
			int stepIndex = emit.baseLifeTimeStep;
			if (emit.varianceTimeStep != 0)
				stepIndex += system.systemRandom.Next(emit.varianceTimeStep);
			stepIndex = Math.Max(1, stepIndex);

			//lifespan in steps
			int life = stepIndex;

			//remove step
			stepIndex = (stepIndex + step) & timeStepMask;

			//create the particle
			Particle particle = new Particle();
			particle.index = particleCapacityF++;

			particle.previousParticleIndexForTimeStep = uint.MaxValue;
			particle.nextParticleIndexForTimeStep = uint.MaxValue;
			particle.addActionIndex = addActionCount;

			if (timeSteps[stepIndex].count++ != 0)
			{
				//step isn't empty?
				uint previousFirst = timeSteps[stepIndex].firstParticleIndex;

				particle.nextParticleIndexForTimeStep = previousFirst;
				particles[previousFirst].previousParticleIndexForTimeStep = index;
			}

			//start of the linked list
			timeSteps[stepIndex].firstParticleIndex = index;

			particle.timeStepIndex = (ushort)stepIndex;
			//store
			this.particles[index] = particle;

			//create the addAction
			AddAction action = new AddAction();
			action.index = index;
			action.lifeSteps = (uint)life;
			action.indexF = particle.index;

			action.cloneFromIndex = sourceIndex;
			action.cloneFromIndexF = sourceIndexF;
			action.cloneTypeIndex = emit.emitFromTypeIndex;

			//if sourceIndex is -1, then this is a root level particle,
			//so it's positin is set by the application.

			if (sourceIndex == -1)
			{
				system.GetSpawnDetails(out action.spawnDetails);
			}

			typeEmitDependancy[emit.emitFromTypeIndex + 1] = true;
		
			//cannot spawn more than 32k particles in a single frame
			if (addActionCount != (ushort)short.MaxValue)
			{
				addActions[addActionCount] = action;

				if (++addActionCount == addActions.Length)
					Array.Resize(ref addActions, addActions.Length * 2);
			}
		}
		//void ValidateSteps()
		//{
		//    for (int i = 0; i < this.timeSteps.Length; i++)
		//    {
		//        uint prev = uint.MaxValue;
		//        uint index = this.timeSteps[i].firstParticleIndex;
		//
		//        for (int p = 0; p < this.timeSteps[i].count; p++)
		//        {
		//            if (this.particles[index].previousParticleIndexForTimeStep != prev)
		//                throw new ArgumentException();
		//            prev = index;
		//            index = this.particles[index].nextParticleIndexForTimeStep;
		//        }
		//
		//        if (this.timeSteps[i].count > 0 && index != uint.MaxValue)
		//            throw new ArgumentException();
		//    }
		//}


		//the meat of the system
		public void Update(ParticleSystem system, int step)
		{
			int stepIndex = step & timeStepMask;

			SystemTimeStep timestep = timeSteps[stepIndex];
			timeSteps[stepIndex] = new SystemTimeStep();
			uint particleIndex = timestep.firstParticleIndex;



			//run per frame logic for the type
			if (frameEmitter != null)
				frameEmitter.RunParticleType(system, this, step);


			//iterate twice.
			//first pass, generate the operations to remove the particles
			//in the second pass, run the remove emitter, if there is one.
			//this way, a particle created in the removed emitter will not be rearranged
			//by another removed particle later

			//this is mostly for the benfit of the GPU system
			//
			uint copyCount = copyActionCount;

			if (timestep.count > 0)
			{
				Particle particle, replace;

				//first, collect the indices for removal, if they exist
				if (removeEmitter != null)
				{
					uint removeIndex = particleIndex;

					int count = 2;
					while (timestep.count > count)
						count *= 2;
					if (removeIndices == null || count > removeIndices.Length)
						Array.Resize(ref removeIndices, count);
					RemoveIndex indexEntry;

					for (int i = 0; i < timestep.count; i++)
					{
						particle = this.particles[removeIndex];

						indexEntry.index = removeIndex;
						indexEntry.indexF = particle.index;
						removeIndices[i] = indexEntry;

						removeIndex = particle.nextParticleIndexForTimeStep;
					}
				}


				//now remove them
				for (int i = 0; i < timestep.count; i++)
				{
					particle = this.particles[particleIndex];


					--particleCapacityF;
					uint last = --particleCapacity;


					//move last particle into this one's position
					replace = this.particles[last];
					
					//unless it's being removed anyway
					if (particleIndex != last)
					{
						//update the linked list indexing of the particles...
						if (replace.previousParticleIndexForTimeStep != uint.MaxValue)
							this.particles[replace.previousParticleIndexForTimeStep].nextParticleIndexForTimeStep = particleIndex;
						else
						{
							if (replace.timeStepIndex != stepIndex)
								this.timeSteps[replace.timeStepIndex].firstParticleIndex = particleIndex;
						}

						//particle has been moved once already in this update? (rare)
						if (replace.nextParticleIndexForTimeStep != uint.MaxValue)
							this.particles[replace.nextParticleIndexForTimeStep].previousParticleIndexForTimeStep = particleIndex;

						//may be moving the next particle in the list...
						if (particle.nextParticleIndexForTimeStep == last)
							particle.nextParticleIndexForTimeStep = particleIndex;

						//store the copy action...
						//but first...
						if (replace.addActionIndex < addActionCount &&
							this.addActions[replace.addActionIndex].index == last)
						{
							//this particle was just added in this frame, now it's being moved
							//so modify the add action instead to directly write to the position
							this.addActions[replace.addActionIndex].index = particleIndex;
							this.addActions[replace.addActionIndex].indexF = particle.index;
						}
						else
						{

							if (replace.addActionIndex >= short.MaxValue) // add action indices above 32k are for copy indices
							{
								//the particle is already being copied...
								//so modify the existing copy op
								copyActions[replace.addActionIndex - short.MaxValue].indexTo = particleIndex;
								copyActions[replace.addActionIndex - short.MaxValue].indexToF = particle.index;
							}
							else
							{

								//otherwise do a copy
								CopyAction copy = new CopyAction();

								copy.indexTo = particleIndex;
								copy.indexToF = particle.index;

								copy.indexFrom = last;
								copy.indexFromF = replace.index;

								replace.addActionIndex = (ushort)(short.MaxValue + copyActionCount);

								copyActions[copyActionCount] = copy;
								if (++copyActionCount == copyActions.Length)
									Array.Resize(ref copyActions, copyActions.Length * 2);
							}
						}


						replace.index = particle.index;
						this.particles[particleIndex] = replace;
					}

					particleIndex = particle.nextParticleIndexForTimeStep;
				}

				//now finally run the remove emitters.
				if (removeEmitter != null)
				{
					RemoveIndex index;

					for (int i = 0; i < timestep.count; i++)
					{
						index = removeIndices[i];

						if (removeEmitter != null)
							removeEmitter.RunParticle(system, this, index.index, index.indexF, step);
					}
				}
			}

			for (uint i = copyCount; i < copyActionCount; i++)
			{
				this.particles[copyActions[i].indexTo].addActionIndex = 0;
			}
		}
		//run particle logic every so 'value' steps
		internal void RunParticleTypeEvery(ParticleSystem system, int step, int value, ref ParticleSystemActionData child)
		{
			//int stepBase = step + timeStepCount;
				
			if (value > 3)
			{
				//step is getting pretty big...
				//so...
				//don't loop all the particles, loop the timesteps that match
				//then loop all their particles.
				//this accesses less data but jumps around a lot.

				SystemTimeStep timestep;
				for (int t = 0; t < this.timeStepCount; t += value)
				{
					//this step is affected, so iterate all it's children.
					timestep = this.timeSteps[(step + t) & timeStepMask];
					uint index = timestep.firstParticleIndex;

					for (int i = 0; i < timestep.count; i++)
					{
						child.RunParticleChildren(system, this, index, this.particles[index].index, step);

						index = particles[index].nextParticleIndexForTimeStep;
					}
				}
			}
			else
			{
				uint cap =particleCapacity;
				float f = 0;
				for (uint i = 0; i < cap; i++)
				{
					if (((step + particles[i].timeStepIndex) % value) == 0)
						child.RunParticleChildren(system, this, i, f, step);
					f++;
				}
			}
		}
		//run particle logic one particle at a time
		internal void RunParticleTypeOneByOne(ParticleSystem system, int step, ref ParticleSystemActionData child)
		{
			uint cap = particleCapacity;
			float f = 0;
			for (uint i = 0; i < cap; i++)
				child.RunParticle(system, this, i,f++, step);
		}
		//emit a particle from every particle
		public void EmitEach(ParticleSystem system, ParticleSystemEmitData emit, int step)
		{
			//emits one particle from every particle.
			//don't want to emit from a particle being emitted... (recursive emit)
			int cap = (int)particleCapacity;

			float f = 0;
			for (int i = 0; i < cap; i++)
				system.Emit(emit,i,f++);
		}
示例#8
0
		protected override void Initialise()
		{
			var tutorials = new Dictionary<string, Type>();
			Program.FindTutorials(tutorials);
			
			Camera3D camera = new Camera3D();

			drawToScreen = new DrawTargetScreen(camera);
			
			backgroundParticles = new ParticleSystem(this.UpdateManager);
			backgroundParticles.GlobalValues[0] = ArrowXOffset;
			backgroundParticles.GlobalValues[2] = (float)this.WindowWidth;
			backgroundParticles.GlobalValues[3] = (float)this.WindowHeight;

			particlesTarget = new DrawTargetTexture2D(camera, this.WindowWidth, this.WindowHeight, SurfaceFormat.Color, DepthFormat.None);
			particlesBlurred = new DrawTargetTexture2D(camera, this.WindowWidth / 2, this.WindowHeight / 2, SurfaceFormat.Color, DepthFormat.None);

			DrawTargetTexture2D inter0 = null, inter1 = null;
			quaterDownsample = new TextureDownsample(particlesTarget, particlesBlurred, ref inter0, ref inter1, particlesBlurred.Width, particlesBlurred.Height);

			inter0 = new DrawTargetTexture2D(camera, particlesBlurred.Width, particlesBlurred.Height, SurfaceFormat.Color, DepthFormat.None);
			blurFilter = new BlurFilter(BlurFilterFormat.SevenSampleBlur, 1, particlesBlurred, inter0);

			backroundDrawer = new VelocityBillboardParticles2DElement(backgroundParticles, false);
			particlesTarget.Add(backroundDrawer);

			//draw the resolved particles to the screen
			drawToScreen.Add(new TexturedElement(particlesTarget, new Vector2(1, 1), true));

			//background block other elements are inserted into. invisible
			var selectionBlock = new Xen.Ex.Graphics2D.SolidColourElement(new Color(0, 0, 0, 0), new Vector2(ElementWidth, tutorials.Count * ElementSeparation));
			selectionBlock.AlphaBlendState = AlphaBlendState.Alpha;
			selectionBlock.VerticalAlignment = VerticalAlignment.Top;

			this.menuBlock = selectionBlock;

			int y_pos = 0;
			foreach (var tutorial in tutorials)
			{
				var tut_item = new TutorialSelection(tutorial.Key, y_pos, this.Content, selectionBlock, this.UpdateManager, tutorial.Value);

				y_pos -= ElementSeparation;
				buttons.Add(tut_item);
			}

			drawToScreen.Add(selectionBlock);	

			var bloom = new TexturedElement(particlesBlurred, new Vector2(1, 1), true);
			bloom.AlphaBlendState = AlphaBlendState.AdditiveSaturate;
			drawToScreen.Add(bloom);

			this.logo = new TexturedElement(new Vector2(282,100));
			this.logo.VerticalAlignment = VerticalAlignment.Top;
			this.logo.HorizontalAlignment = HorizontalAlignment.Centre;
			this.logo.Position = new Vector2(0, -50);

			this.helperText = new TextElementRect(new Vector2(800,100),"Use the DPAD to select an item, press 'A' to run the example\nWhen running an example, press 'back' to return to this menu");
			this.helperText.VerticalAlignment = VerticalAlignment.Bottom;
			this.helperText.HorizontalAlignment = HorizontalAlignment.Centre;
			this.helperText.TextHorizontalAlignment = TextHorizontalAlignment.Centre;
			this.helperText.TextVerticalAlignment = VerticalAlignment.Centre;
			this.helperText.Colour = Color.Gray;

			drawToScreen.Add(logo);
			drawToScreen.Add(helperText);
		}
        private void SetParticles(ContentState state)
        {
            if (_level == 2)
            {
                ParticleSystem particles = new ParticleSystem(state.Application.UpdateManager);
                followingParticles.Add(particles);
                drawToScreen.Add(new BillboardParticles3D(particles));
                particles.ParticleSystemData = state.Load<ParticleSystemData>("Particles/Mist");
            }
            if (_level == 3)
            {
                ParticleSystem particles = new ParticleSystem(state.Application.UpdateManager);

                followingParticles.Add(particles);

                ParticleDrawer3D fogDrawer = new BillboardParticles3D(particles);
                ParticleDrawer3D snowDrawer = new VelocityBillboardParticles3D(particles, false, 0.1f);
                
                drawToScreen.Add(fogDrawer);
                drawToScreen.Add(snowDrawer);

                particles.ParticleSystemData = state.Load<ParticleSystemData>("Particles/Snow");

                fogDrawer.SetParticleTypeDrawMask("fog", true);
                fogDrawer.SetParticleTypeDrawMask("snow", false);

                snowDrawer.SetParticleTypeDrawMask("fog", false);
                snowDrawer.SetParticleTypeDrawMask("snow", true);

                
            }
            else if (_level == 2)
            {
            }
        }
		protected override void Initialise()
		{
			//draw targets usually need a camera.
			var camera = new Xen.Camera.FirstPersonControlledCamera3D(this.UpdateManager, Vector3.Zero, false);

			//don't allow the camera to move too fast
			camera.MovementSensitivity *= 0.1f;
			camera.LookAt(new Vector3(0,3,0), new Vector3(1, 5, 10), new Vector3(0, 1, 0));
			
			//create the draw target.
			drawToScreen = new DrawTargetScreen(camera);
			drawToScreen.ClearBuffer.ClearColour = new Color(45,50,60);

			
			//create the fire and smoke particle system
			this.fireParticleSystem = new ParticleSystem(this.UpdateManager);
			this.smokeParticleSystem = new ParticleSystem(this.UpdateManager);

			//IMPORTANT
			//The following flags are FALSE by default.
			//For looping effects, such as the fire and smoke, it's highly
			//recommended to enable this flag. Otherwise, while the effect
			//is offscreen, the particle system will continue to process.
			this.fireParticleSystem.PauseUpdatingWhileCulled = true;
			this.smokeParticleSystem.PauseUpdatingWhileCulled = true;


			this.drawSorted = new Xen.Ex.Scene.DepthDrawSorter(Xen.Ex.Scene.DepthSortMode.BackToFront);
			this.drawUnsorted = new DrawList();

			var fireDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles3D(this.fireParticleSystem, true);
			var smokeDrawer = new Xen.Ex.Graphics.Display.BillboardParticles3D(this.smokeParticleSystem);

			for (int i = 0; i < 10; i++)
			{
				Vector3 position = new Vector3((float)Math.Cos(i * Math.PI / 5.0) * 6.0f, 0, (float)Math.Sin(i * Math.PI / 5.0) * 6.0f);
				
				CullableParticleWrapper fireEffect, smokeEffect;

				fireEffect = new CullableParticleWrapper(fireDrawer, position, new Vector3(0, 2, 0), 4);
				smokeEffect = new CullableParticleWrapper(smokeDrawer, position, new Vector3(0, 6, 0), 5);

				this.drawSorted.Add(fireEffect);
				this.drawSorted.Add(smokeEffect);

				this.drawUnsorted.Add(fireEffect);
				this.drawUnsorted.Add(smokeEffect);

				var light = new GroundLightDisk(position);
				this.drawSorted.Add(light);
				this.drawUnsorted.Add(light);
			}


			//setup the burst effect
			this.burstParticleSystem = new ParticleSystem(this.UpdateManager);

			//for this case, PauseUpdatingWhileCulled is not set to true.
			//The particle emitting is culled when offscreen. If set to true,
			//Any particles left offscreen could 'pause', when they naturally
			//wouldn't be emitted anyway.
			//(The particle system will use very few resources when it has no
			//active particles)

			this.burstSources = new BurstSource[20];
			Random rand = new Random();

			for (int i = 0; i < this.burstSources.Length; i++)
			{
				//create the bursts out in the distance
				Vector3 position = new Vector3((float)i * 5.0f - this.burstSources.Length * 2.5f, 0, -20); 
				float radius = 10; // with a decent radius

				//give them a random starting time
				this.burstSources[i] = new BurstSource(position, radius, (float)rand.NextDouble() * 2);

				this.drawSorted.Add(this.burstSources[i]);
				this.drawUnsorted.Add(this.burstSources[i]);
			}

			//the bursts need to be drawn as a group..
			var burstDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles3D(this.burstParticleSystem,false,0.5f);

			this.drawSorted.Add(burstDrawer);
			this.drawUnsorted.Add(burstDrawer);

			//Use all the burst sources to cull the drawer (may not be ideal if there were many sources...)
			//Use the particle drawer CullProxy to do it
			burstDrawer.CullProxy = new BurstCullProxy(this.burstSources);
			


			//add a ground plane to show the horizon
			drawToScreen.Add(new Tutorial_22.DarkGroundPlane(new Vector4(0.125f,0.15f,0.135f,1)));

			//add the sorted and unsorted lists
			drawToScreen.Add(drawSorted);
			drawToScreen.Add(drawUnsorted);


			//finally, create a CullTestVisualizer, which will visually show the cull tests performed
			cullTestVisualizer = new Xen.Ex.Scene.CullTestVisualizer();

			//the visualizer is added as a draw modifier
			this.drawToScreen.AddModifier(cullTestVisualizer);

			//add help text
			this.text = new TextElement();
			this.text.VerticalAlignment = VerticalAlignment.Bottom;
			this.text.Position = new Vector2(50, 100);
			drawToScreen.Add(this.text);

			//add draw stats
			stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
			drawToScreen.Add(stats);
		}
		/// <summary>
		/// Construct the particle drawer
		/// </summary>
		/// <param name="system"></param>
		/// <param name="useRotationValueToScaleVelocityEffect"><para>When true, the per particle rotation value will be used to scale the velocity stretching effect</para><para>Allowing per-particle scaling based on velocity</para></param>
		public VelocityBillboardParticles2DElement(ParticleSystem system, bool useRotationValueToScaleVelocityEffect)
			: base(system)
		{
			this.useRotationToScaleVelocityEffect = useRotationValueToScaleVelocityEffect;
		}
		/// <summary>
		/// Construct the Velocity Billboard particles
		/// </summary>
		/// <param name="system"></param>
		/// <param name="useRotationValueToScaleVelocityEffect"><para>When true, the per particle rotation value will be used to scale the velocity stretching effect</para><para>Allowing per-particle scaling based on velocity</para></param>
		/// <param name="velocityExtentionScale">Scale factor to extend the particles</param>
		public VelocityBillboardParticles2DElement(ParticleSystem system, bool useRotationValueToScaleVelocityEffect, float velocityExtentionScale)
			: base(system)
		{
			this.UseRotationValueToScaleVelocityEffect = useRotationValueToScaleVelocityEffect;
			this.VelocityExtentionScale = velocityExtentionScale;
		}