/// <summary> /// draws the registered sprite objects by using the sprite batch. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { if (TextureResource == null) { throw new InvalidOperationException("The texture is empty"); } else if (TextureResource.IsDisposed) { throw new ObjectDisposedException("TextureResource"); } for (int i = 0; i < spriteList.Count; i++) { Sprite2DObject sprite = spriteList[i]; if (sprite != null) { // If active visible if (sprite.Visible) { renderTracer.SpriteBatch.Draw(TextureResource, sprite.ScreenRectangle, sprite.SourceRectangle, sprite.Color); } } } }
/// <summary> /// draw up in order every scene node when before drawing and draw scene. /// </summary> protected void DrawSort(RenderTracer renderTracer, bool ascending) { int nodeCount = 0; // fill in sort array. for (int i = 0; i < ChildCount; i++) { GameSceneNode child = GetChild(i) as GameSceneNode; if (child.Visible) { Matrix modelView = child.TransformedMatrix * renderTracer.View; sortArray[nodeCount].node = child; sortArray[nodeCount].depth = modelView.Translation.Length(); nodeCount++; } } // draw every scene node using quick sort algorithm. QuickSort(ref sortArray, 0, nodeCount - 1, ascending); // draw every sorted node in array. for (int i = 0; i < nodeCount; i++) { sortArray[i].node.Draw(renderTracer); sortArray[i].Clear(); } }
public RenderingCustomEffectEventArgs(RenderTracer renderTracer, ModelMesh mesh, Effect effect, Matrix world) : base() { this.renderTracer = renderTracer; this.mesh = mesh; this.effect = effect; this.world = world; }
/// <summary> /// draws string on screens by using the information stored in TextItem. /// Internally, the sprite batch’s Begin() function and the End() function /// are not called. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { renderTracer.SpriteBatch.DrawString(this.textItem.Font, this.textItem.Text, new Vector2(this.textItem.PosX, this.textItem.PosY), this.textItem.Color, this.textItem.Rotation, Vector2.Zero, this.textItem.Scale, SpriteEffects.None, 1.0f); }
/// <summary> /// It draws itself and child nodes. /// When "Visible" is set to false, it will not get executed. /// </summary> public virtual void Draw(RenderTracer renderTracer) { // If not set to visible, it will not draw. if (Visible) { switch (orderWhenDraw) { case DrawOrderType.None: { // Draw itself OnDraw(renderTracer); // Draw each child node if (childList != null) { for (int i = 0; i < childList.Count; i++) { GameSceneNode gameSceneNode = childList[i] as GameSceneNode; if ((gameSceneNode != null) && gameSceneNode.Visible) { gameSceneNode.Draw(renderTracer); } } } } break; case DrawOrderType.Ascending: { // draw up in order DrawSort(renderTracer, true); } break; case DrawOrderType.Descending: { // draw up in order DrawSort(renderTracer, false); } break; } } }
/// <summary> /// draws a 3D quad. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { World = this.TransformedMatrix; View = renderTracer.View; Projection = renderTracer.Projection; renderTracer.Device.VertexDeclaration = vertexDecl; renderTracer.Device.RenderState.AlphaTestEnable = alphaTestEnable; renderTracer.Device.RenderState.AlphaBlendEnable = alphaBlendEnable; renderTracer.Device.RenderState.AlphaFunction = alphaFunction; renderTracer.Device.RenderState.SourceBlend = sourceBlend; renderTracer.Device.RenderState.DestinationBlend = destinationBlend; renderTracer.Device.RenderState.BlendFunction = blendFunction; renderTracer.Device.RenderState.ReferenceAlpha = referenceAlpha; renderTracer.Device.RenderState.DepthBufferEnable = depthBufferEnable; renderTracer.Device.RenderState.DepthBufferWriteEnable = depthBufferWriteEnable; renderTracer.Device.RenderState.DepthBufferFunction = depthBufferFunction; renderTracer.Device.RenderState.CullMode = cullMode; GraphicsDevice device = renderTracer.Device; effect.Begin(); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Begin(); device.DrawUserIndexedPrimitives <VertexPositionNormalTexture>( PrimitiveType.TriangleList, this.vertices, 0, 4, this.indices, 0, 2); pass.End(); } effect.End(); }
/// <summary> /// draws the registered sprite objects by using the sprite batch. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { if (TextureResource == null) throw new InvalidOperationException("The texture is empty"); else if (TextureResource.IsDisposed ) throw new ObjectDisposedException("TextureResource"); for (int i = 0; i < spriteList.Count; i++) { Sprite2DObject sprite = spriteList[i]; if (sprite != null) { // If active visible if (sprite.Visible ) { renderTracer.SpriteBatch.Draw(TextureResource, sprite.ScreenRectangle, sprite.SourceRectangle, sprite.Color); } } } }
/// <summary> /// updates the vertex data and draws /// It always looks at the view matrix at the center between /// the begin point and the end point of the billboard. /// </summary> /// <param name="renderTracer">render information</param> protected override void OnDraw(RenderTracer renderTracer) { int count = 0; for (int i = 0; i < objectCount; i++) { if (billboardList[i].Enable == false) continue; count++; } if (count == 0) return; PrimitiveCount = count * 2; UpdateVertexCount = objectCount * vertexStride; // needs to update? if (renderTracer.View != lastViewMatrix) { needToUpdate = true; this.lastViewMatrix = renderTracer.View; } if (alwaysUpdate || needToUpdate) { int vertexOffset = 0; int indexOffset = 0; // calculates inverse view matrix. Matrix billboardMatrix = this.TransformedMatrix * renderTracer.View; billboardMatrix = Helper3D.Transpose(billboardMatrix); // gets inverse view direction. Vector3 invertViewAt = billboardMatrix.Forward; invertViewAt.Normalize(); for (int i = 0; i < objectCount; i++) { BillboardObject obj = billboardList[i]; if (obj.Enable == false) continue; Vector3 vec = Vector3.Zero; Vector3 dir = Vector3.Zero; dir = obj.End - obj.Start; dir.Normalize(); Vector3.Cross(ref dir, ref invertViewAt, out vec); vec.Normalize(); // updates vertex positions. SetBufferPosition(ref vertexData, obj, vertexOffset, vec); // updates texture coordinates. SetBufferTextureCoord(ref vertexData, obj, vertexOffset, renderingSpace); // updates vertex colors. SetBufferColor(ref vertexData, obj, vertexOffset); indexData[indexOffset + 0] = (short)(vertexOffset + 0); indexData[indexOffset + 1] = (short)(vertexOffset + 2); indexData[indexOffset + 2] = (short)(vertexOffset + 1); indexData[indexOffset + 3] = (short)(vertexOffset + 1); indexData[indexOffset + 4] = (short)(vertexOffset + 2); indexData[indexOffset + 5] = (short)(vertexOffset + 3); vertexOffset += vertexStride; indexOffset += indexStride; } if (userPrimitive == false) { // binds the vertex buffer. BindVertexBuffer(); // binds the index buffer. BindIndexBuffer(); } if (needToUpdate) needToUpdate = false; } // draws mesh base.OnDraw(renderTracer); }
protected override void OnDraw(RenderTracer renderTracer) { RenderState renderState = renderTracer.Device.RenderState; // Transform culling sphere if (enableCulling) { cullingSphere.Center = Vector3.Transform(cullingSphereLocalCenter, RootAxis * Collide.TransformMatrix); // Check if the the model is contained inside or intersecting // with the frustum. ContainmentType cullingResult = renderTracer.Frustum.Contains(cullingSphere); // Draw a the model If inside in the frustum if (cullingResult == ContainmentType.Disjoint) { return; } } renderState.AlphaTestEnable = alphaTestEnable; renderState.AlphaBlendEnable = alphaBlendEnable; renderState.AlphaFunction = alphaFunction; renderState.SourceBlend = sourceBlend; renderState.DestinationBlend = destinationBlend; renderState.BlendFunction = blendFunction; renderState.ReferenceAlpha = referenceAlpha; renderState.DepthBufferEnable = depthBufferEnable; renderState.DepthBufferWriteEnable = depthBufferWriteEnable; renderState.DepthBufferFunction = depthBufferFunction; renderState.CullMode = cullMode; // Draw the model. for (int i = 0; i < ModelData.model.Meshes.Count; i++) { ModelMesh mesh = ModelData.model.Meshes[i]; for (int j = 0; j < mesh.Effects.Count; j++) { // call a entried custom effect processing if (RenderingCustomEffect != null) { // Shader custom processing RenderingCustomEffect(this, new RenderingCustomEffectEventArgs(renderTracer, mesh, mesh.Effects[j], BoneTransforms[mesh.ParentBone.Index])); } else if (mesh.Effects[j] is BasicEffect) { BasicEffect effect = (BasicEffect)mesh.Effects[j]; // Apply fog if (renderTracer.Fog != null && ActiveFog) { RenderFog fog = renderTracer.Fog; effect.FogEnabled = fog.enabled; if (effect.FogEnabled) { effect.FogStart = fog.start; effect.FogEnd = fog.end; effect.FogColor = fog.color.ToVector3(); } } else { effect.FogEnabled = false; } if (ActiveLighting) { // Apply lighting if (renderTracer.Lighting != null) { RenderLighting lighting = renderTracer.Lighting; effect.LightingEnabled = lighting.enabled; if (effect.LightingEnabled) { effect.AmbientLightColor = lighting.ambientColor.ToVector3(); effect.DirectionalLight0.Enabled = true; effect.DirectionalLight0.Direction = lighting.direction; effect.DirectionalLight0.DiffuseColor = lighting.diffuseColor.ToVector3(); effect.DirectionalLight0.SpecularColor = lighting.specularColor.ToVector3(); } } if (Lighting != null) { effect.LightingEnabled = true; for (int cnt = 0; cnt < Lighting.Length; cnt++) { RenderLighting lighting = Lighting[cnt]; BasicDirectionalLight basicLight = null; if (cnt == 0) { basicLight = effect.DirectionalLight1; } else if (cnt == 1) { basicLight = effect.DirectionalLight2; } else { continue; } if (lighting.enabled) { basicLight.Enabled = true; basicLight.Direction = lighting.direction; basicLight.DiffuseColor = lighting.diffuseColor.ToVector3(); basicLight.SpecularColor = lighting.specularColor.ToVector3(); } else { basicLight.Enabled = false; } } } if (renderTracer.Lighting == null && Lighting == null) { effect.LightingEnabled = false; } // Apply material if (Material != null) { effect.Alpha = Material.alpha; effect.DiffuseColor = Material.diffuseColor.ToVector3(); effect.SpecularColor = Material.specularColor.ToVector3(); effect.SpecularPower = Material.specularPower; effect.EmissiveColor = Material.emissiveColor.ToVector3(); effect.VertexColorEnabled = Material.vertexColorEnabled; effect.PreferPerPixelLighting = Material.preferPerPixelLighting; } } else { effect.LightingEnabled = false; } // Apply transform effect.World = BoneTransforms[mesh.ParentBone.Index]; effect.View = renderTracer.View; effect.Projection = renderTracer.Projection; } } mesh.Draw(); } }
/// <summary> /// the mesh is drawn by using the vertexData. /// When the userPrimitive member is set to true, /// it is drawn without using the vertex buffer and the index buffer. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { GraphicsDevice device = renderTracer.Device; RenderState renderState = device.RenderState; basicEffect.Texture = this.textureResource; basicEffect.World = this.TransformedMatrix; basicEffect.View = renderTracer.View; basicEffect.Projection = renderTracer.Projection; basicEffect.LightingEnabled = false; device.VertexDeclaration = vertexDeclaration; device.SamplerStates[0].AddressU = TextureAddressMode.Wrap; device.SamplerStates[0].AddressV = TextureAddressMode.Wrap; device.SamplerStates[0].MinFilter = TextureFilter.Linear; device.SamplerStates[0].MagFilter = TextureFilter.Linear; device.SamplerStates[0].MipFilter = TextureFilter.Point; renderState.AlphaTestEnable = alphaTestEnable; renderState.AlphaBlendEnable = alphaBlendEnable; renderState.AlphaFunction = alphaFunction; renderState.SourceBlend = sourceBlend; renderState.DestinationBlend = destinationBlend; renderState.BlendFunction = blendFunction; renderState.ReferenceAlpha = referenceAlpha; renderState.DepthBufferEnable = depthBufferEnable; renderState.DepthBufferWriteEnable = depthBufferWriteEnable; renderState.DepthBufferFunction = depthBufferFunction; renderState.CullMode = cullMode; basicEffect.Begin(); for (int i = 0; i < basicEffect.CurrentTechnique.Passes.Count; i++) { EffectPass pass = basicEffect.CurrentTechnique.Passes[i]; pass.Begin(); if (userPrimitive) { // Use index? if (indexData != null) { // only use vertex and index data device.DrawUserIndexedPrimitives <VertexPositionColorTexture>( PrimitiveType.TriangleList, vertexData, 0, vertexData.Length, indexData, 0, this.primitiveCount); } else { device.DrawUserPrimitives <VertexPositionColorTexture>( PrimitiveType.TriangleList, vertexData, 0, this.primitiveCount); } } else { // Use vertex buffer device.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColorTexture.SizeInBytes); // Use index? if (indexBuffer != null) { // Use index buffer device.Indices = indexBuffer; device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, updateVertexCount, 0, this.primitiveCount); } else { device.DrawPrimitives(PrimitiveType.TriangleList, 0, this.primitiveCount); } } pass.End(); } basicEffect.End(); device.RenderState.DepthBufferWriteEnable = true; }
protected override void OnDraw(RenderTracer renderTracer) { base.OnDraw(renderTracer); }
/// <summary> /// draws a 3D quad. /// </summary> /// <param name="renderTracer"></param> protected override void OnDraw(RenderTracer renderTracer) { World = this.TransformedMatrix; View = renderTracer.View; Projection = renderTracer.Projection; renderTracer.Device.VertexDeclaration = vertexDecl; renderTracer.Device.RenderState.AlphaTestEnable = alphaTestEnable; renderTracer.Device.RenderState.AlphaBlendEnable = alphaBlendEnable; renderTracer.Device.RenderState.AlphaFunction = alphaFunction; renderTracer.Device.RenderState.SourceBlend = sourceBlend; renderTracer.Device.RenderState.DestinationBlend = destinationBlend; renderTracer.Device.RenderState.BlendFunction = blendFunction; renderTracer.Device.RenderState.ReferenceAlpha = referenceAlpha; renderTracer.Device.RenderState.DepthBufferEnable = depthBufferEnable; renderTracer.Device.RenderState.DepthBufferWriteEnable = depthBufferWriteEnable; renderTracer.Device.RenderState.DepthBufferFunction = depthBufferFunction; renderTracer.Device.RenderState.CullMode = cullMode; GraphicsDevice device = renderTracer.Device; effect.Begin(); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Begin(); device.DrawUserIndexedPrimitives<VertexPositionNormalTexture>( PrimitiveType.TriangleList, this.vertices, 0, 4, this.indices, 0, 2); pass.End(); } effect.End(); }
/// <summary> /// When Draw() function is executed, it will be called automatically. /// It gets overridden and defined externally. /// When the parent is called, the child also gets called. /// </summary> protected virtual void OnDraw(RenderTracer renderTracer) { }
/// <summary> /// updates the vertex data and draws /// </summary> /// <param name="renderTracer">render information</param> protected override void OnDraw(RenderTracer renderTracer) { int objectCount = 0; for (int i = 0; i < this.count; i++) { if (spriteList[i].Enable == false) continue; objectCount++; } if (objectCount == 0) return; PrimitiveCount = objectCount * 2; UpdateVertexCount = this.count * vertexStride; // needs to update? if (renderTracer.View != lastViewMatrix) { needToUpdate = true; this.lastViewMatrix = renderTracer.View; } if (alwaysUpdate || needToUpdate) { int vertexOffset = 0; int indexOffset = 0; for (int i = 0; i < this.count; i++) { Sprite3DObject obj = spriteList[i]; if (obj.Enable == false) continue; // rotates the paticle by z-axis. (Sprite3D can rotate) Matrix transformMatrix = Matrix.CreateRotationZ(obj.Rotation) * Helper3D.Transpose( this.TransformedMatrix * renderTracer.View); // updates vertex positions. SetBufferPosition(ref vertexData, obj, vertexOffset, transformMatrix, this.renderingSpace); // updates texture coordinates. SetBufferTextureCoord(ref vertexData, obj, vertexOffset, this.renderingSpace); // updates vertex colors. SetBufferColor(ref vertexData, obj, vertexOffset); indexData[indexOffset + 0] = (short)(vertexOffset + 0); indexData[indexOffset + 1] = (short)(vertexOffset + 2); indexData[indexOffset + 2] = (short)(vertexOffset + 1); indexData[indexOffset + 3] = (short)(vertexOffset + 1); indexData[indexOffset + 4] = (short)(vertexOffset + 2); indexData[indexOffset + 5] = (short)(vertexOffset + 3); vertexOffset += vertexStride; indexOffset += indexStride; } if (userPrimitive == false) { // binds the vertex buffer. BindVertexBuffer(); // binds the index buffer. BindIndexBuffer(); } if (needToUpdate) needToUpdate = false; } // draws mesh base.OnDraw(renderTracer); }
/// <summary> /// updates the vertex data and draws /// It always looks at the view matrix at the center between /// the begin point and the end point of the billboard. /// </summary> /// <param name="renderTracer">render information</param> protected override void OnDraw(RenderTracer renderTracer) { int count = 0; for (int i = 0; i < objectCount; i++) { if (billboardList[i].Enable == false) { continue; } count++; } if (count == 0) { return; } PrimitiveCount = count * 2; UpdateVertexCount = objectCount * vertexStride; // needs to update? if (renderTracer.View != lastViewMatrix) { needToUpdate = true; this.lastViewMatrix = renderTracer.View; } if (alwaysUpdate || needToUpdate) { int vertexOffset = 0; int indexOffset = 0; // calculates inverse view matrix. Matrix billboardMatrix = this.TransformedMatrix * renderTracer.View; billboardMatrix = Helper3D.Transpose(billboardMatrix); // gets inverse view direction. Vector3 invertViewAt = billboardMatrix.Forward; invertViewAt.Normalize(); for (int i = 0; i < objectCount; i++) { BillboardObject obj = billboardList[i]; if (obj.Enable == false) { continue; } Vector3 vec = Vector3.Zero; Vector3 dir = Vector3.Zero; dir = obj.End - obj.Start; dir.Normalize(); Vector3.Cross(ref dir, ref invertViewAt, out vec); vec.Normalize(); // updates vertex positions. SetBufferPosition(ref vertexData, obj, vertexOffset, vec); // updates texture coordinates. SetBufferTextureCoord(ref vertexData, obj, vertexOffset, renderingSpace); // updates vertex colors. SetBufferColor(ref vertexData, obj, vertexOffset); indexData[indexOffset + 0] = (short)(vertexOffset + 0); indexData[indexOffset + 1] = (short)(vertexOffset + 2); indexData[indexOffset + 2] = (short)(vertexOffset + 1); indexData[indexOffset + 3] = (short)(vertexOffset + 1); indexData[indexOffset + 4] = (short)(vertexOffset + 2); indexData[indexOffset + 5] = (short)(vertexOffset + 3); vertexOffset += vertexStride; indexOffset += indexStride; } if (userPrimitive == false) { // binds the vertex buffer. BindVertexBuffer(); // binds the index buffer. BindIndexBuffer(); } if (needToUpdate) { needToUpdate = false; } } // draws mesh base.OnDraw(renderTracer); }
protected override void OnDraw(RenderTracer renderTracer) { RenderState renderState = renderTracer.Device.RenderState; // Transform culling sphere if (enableCulling ) { cullingSphere.Center = Vector3.Transform(cullingSphereLocalCenter, RootAxis * Collide.TransformMatrix); // Check if the the model is contained inside or intersecting // with the frustum. ContainmentType cullingResult = renderTracer.Frustum.Contains(cullingSphere); // Draw a the model If inside in the frustum if (cullingResult == ContainmentType.Disjoint) return; } renderState.AlphaTestEnable = alphaTestEnable; renderState.AlphaBlendEnable = alphaBlendEnable; renderState.AlphaFunction = alphaFunction; renderState.SourceBlend = sourceBlend; renderState.DestinationBlend = destinationBlend; renderState.BlendFunction = blendFunction; renderState.ReferenceAlpha = referenceAlpha; renderState.DepthBufferEnable = depthBufferEnable; renderState.DepthBufferWriteEnable = depthBufferWriteEnable; renderState.DepthBufferFunction = depthBufferFunction; renderState.CullMode = cullMode; // Draw the model. for( int i = 0; i < ModelData.model.Meshes.Count; i++) { ModelMesh mesh = ModelData.model.Meshes[i]; for (int j = 0; j < mesh.Effects.Count; j++) { // call a entried custom effect processing if (RenderingCustomEffect != null) { // Shader custom processing RenderingCustomEffect(this, new RenderingCustomEffectEventArgs(renderTracer, mesh, mesh.Effects[j], BoneTransforms[mesh.ParentBone.Index])); } else if (mesh.Effects[j] is BasicEffect) { BasicEffect effect = (BasicEffect)mesh.Effects[j]; // Apply fog if (renderTracer.Fog != null && ActiveFog ) { RenderFog fog = renderTracer.Fog; effect.FogEnabled = fog.enabled; if (effect.FogEnabled ) { effect.FogStart = fog.start; effect.FogEnd = fog.end; effect.FogColor = fog.color.ToVector3(); } } else { effect.FogEnabled = false; } if (ActiveLighting ) { // Apply lighting if (renderTracer.Lighting != null) { RenderLighting lighting = renderTracer.Lighting; effect.LightingEnabled = lighting.enabled; if (effect.LightingEnabled ) { effect.AmbientLightColor = lighting.ambientColor.ToVector3(); effect.DirectionalLight0.Enabled = true; effect.DirectionalLight0.Direction = lighting.direction; effect.DirectionalLight0.DiffuseColor = lighting.diffuseColor.ToVector3(); effect.DirectionalLight0.SpecularColor = lighting.specularColor.ToVector3(); } } if (Lighting != null) { effect.LightingEnabled = true; for (int cnt = 0; cnt < Lighting.Length; cnt++) { RenderLighting lighting = Lighting[cnt]; BasicDirectionalLight basicLight = null; if (cnt == 0) basicLight = effect.DirectionalLight1; else if (cnt == 1) basicLight = effect.DirectionalLight2; else continue; if (lighting.enabled ) { basicLight.Enabled = true; basicLight.Direction = lighting.direction; basicLight.DiffuseColor = lighting.diffuseColor.ToVector3(); basicLight.SpecularColor = lighting.specularColor.ToVector3(); } else { basicLight.Enabled = false; } } } if (renderTracer.Lighting == null && Lighting == null) { effect.LightingEnabled = false; } // Apply material if (Material != null) { effect.Alpha = Material.alpha; effect.DiffuseColor = Material.diffuseColor.ToVector3(); effect.SpecularColor = Material.specularColor.ToVector3(); effect.SpecularPower = Material.specularPower; effect.EmissiveColor = Material.emissiveColor.ToVector3(); effect.VertexColorEnabled = Material.vertexColorEnabled; effect.PreferPerPixelLighting = Material.preferPerPixelLighting; } } else { effect.LightingEnabled = false; } // Apply transform effect.World = BoneTransforms[mesh.ParentBone.Index]; effect.View = renderTracer.View; effect.Projection = renderTracer.Projection; } } mesh.Draw(); } }
/// <summary> /// It calls Drive() function by using the data of the ParticleInfo to update /// the information of each ParticleObject’s position, rotation, and scale. /// </summary> /// <param name="renderTracer">render information in the RenderContext</param> protected override void OnDraw(RenderTracer renderTracer) { // Update particle info Drive(renderTracer); }
/// <summary> /// updates the vertex data and draws /// </summary> /// <param name="renderTracer">render information</param> protected override void OnDraw(RenderTracer renderTracer) { int objectCount = 0; for (int i = 0; i < this.count; i++) { if (pointSpriteList[i].Enable == false) { continue; } objectCount++; } if (objectCount == 0) { return; } PrimitiveCount = objectCount * 2; UpdateVertexCount = this.count * vertexStride; this.alwaysUpdate = true; // needs to update? if (renderTracer.View != lastViewMatrix) { needToUpdate = true; this.lastViewMatrix = renderTracer.View; } if (this.alwaysUpdate || needToUpdate) { int vertexOffset = 0; int indexOffset = 0; // calculates inverse view matrix. Matrix transformMatrix = Helper3D.Transpose(this.TransformedMatrix * renderTracer.View); for (int i = 0; i < this.count; i++) { PointSpriteObject obj = pointSpriteList[i]; if (obj.Enable == false) { continue; } // updates vertex positions. SetBufferPosition(ref vertexData, obj, vertexOffset, transformMatrix, this.space); // updates texture coordinates. SetBufferTextureCoord(ref vertexData, obj, vertexOffset, this.space); // updates vertex colors. SetBufferColor(ref vertexData, obj, vertexOffset); indexData[indexOffset + 0] = (short)(vertexOffset + 0); indexData[indexOffset + 1] = (short)(vertexOffset + 1); indexData[indexOffset + 2] = (short)(vertexOffset + 2); indexData[indexOffset + 3] = (short)(vertexOffset + 3); indexData[indexOffset + 4] = (short)(vertexOffset + 0); indexData[indexOffset + 5] = (short)(vertexOffset + 2); vertexOffset += vertexStride; indexOffset += indexStride; } if (userPrimitive == false) { // binds the vertex buffer. BindVertexBuffer(); // binds the index buffer. BindIndexBuffer(); } if (needToUpdate) { needToUpdate = false; } } // draws mesh base.OnDraw(renderTracer); }
/// <summary> /// When the information of each ParticleObject gets updated, /// the vertex values of the GameMesh, GamePointSprite, GameSprite3D, and /// GameBillboard classes are updated. /// </summary> /// <param name="renderTracer">render information in the RenderContext</param> protected void Drive(RenderTracer renderTracer) { int emitCount = 0, aliveCount = 0; float time = 0, s = 0.0f; float lifeTime = 0.0f; Vector3 dir = Vector3.Zero;; bool isEnable = false; bool isEmit = false; bool isInterpolate = false; Matrix mtx = Matrix.Identity; Vector3 vGravDir = Vector3.Zero; bool isUv = false; Vector2 uv1 = Vector2.Zero; Vector2 uv2 = Vector2.Zero; // If the changeTime is false, no update if (changeTime == false) return; else if (changeTime ) changeTime = false; time = (float)renderTracer.GameTime.ElapsedGameTime.TotalSeconds; emitInterval -= time; if (isStopping == false && emitInterval <= 0.0f) { // New particle object emit isEmit = true; emitInterval = Info.EmitInterval; } mtx = this.TransformedMatrix * renderTracer.View; mtx = Helper3D.Transpose(mtx); // Calculate gravity direction vGravDir = Vector3.TransformNormal(globalGravityDirection, mtx ); for (int i = 0; i < Info.MaxObjectCount; i++) { ParticleObject obj = particleObjectList[i]; isEnable = true; isUv = false; lifeTime = 0.0f; // If the object state is deactivate if (!obj.IsState(ParticleObject.States.Enable)) { if ((isEmit ) && (emitCount < Info.EmitCount)) { if (!((Info.Volatile ) && obj.IsState(ParticleObject.States.Fired))) { emitCount++; // Emit a new particle object EmitParticle(ref obj); } else { isEnable = false; } } else { isEnable = false; } } else { // If the object state is activate obj.time += time; lifeTime = obj.time * rObjectLifeTime; if (lifeTime >= 1.0f) { // The object is finished if ((isEmit ) && (Info.Volatile == false)) { // Finished particle object is restarting! emitCount++; // Emit a new particle object EmitParticle(ref obj); lifeTime = 0.0f; } // Has to deactivate else { obj.state &= ~((uint)ParticleObject.States.Enable); isEnable = false; } } } if (isEnable == false) { switch (Info.ParticleType) { case ParticleInfo.ParticleObjectType.PointSprite: { scenePointSprite.SetObjectEnable(i, false); } break; case ParticleInfo.ParticleObjectType.Sprite: { sceneSprite3D.SetObjectEnable(i, false); } break; case ParticleInfo.ParticleObjectType.AnchorBillboard: case ParticleInfo.ParticleObjectType.Billboard: { sceneBillboard.SetUpdateType(i, false); } break; case ParticleInfo.ParticleObjectType.Scene: { sceneMesh.Enabled = false; sceneMesh.Visible = false; } break; } } else { float tempInterval = 0.0f; isInterpolate = true; aliveCount++; ////////////////////////////////////////////////////////// // Position obj.posInterval += time; tempInterval = obj.posInterval; if (tempInterval >= Info.PositionUpdateInterval) { int last = posArgCount - 1; if (Info.PositionUpdateInterval < time) { tempInterval = obj.posInterval = time; isInterpolate = false; } switch (Info.PositionFunc[last]) { case ParticleInfo.FuncType.Constant: { obj.posArg[last] = Info.PositionInit[last]; } break; case ParticleInfo.FuncType.Sin: { obj.posArg[last] = (float)Math.Sin(MathHelper.PiOver2 * lifeTime) * Info.PositionFactor[last]; } break; case ParticleInfo.FuncType.Cos: { obj.posArg[last] = (float)Math.Cos(MathHelper.PiOver2 * lifeTime) * Info.PositionFactor[last]; } break; case ParticleInfo.FuncType.Rnd: { obj.posArg[last] = HelperMath.RandomNormal2(); } break; case ParticleInfo.FuncType.Table: { KeyFrameTable table = Info.PositionTable[last]; obj.posArg[last] = table.GetKeyFrame(lifeTime, positionInterpolate); } break; } obj.posArg[last] *= obj.posRandom; if (last == 1) { // Accelation...v = v0 + at obj.posArg[0] += obj.posArg[1] * tempInterval; } if (Info.IsPositionStyle(ParticleInfo.ParamStyles.Clamp)) { obj.posArg[0] = MathHelper.Clamp(obj.posArg[0], Info.PositionMin, Info.PositionMax); } // Move distance...s = vt s = obj.posArg[0] * tempInterval; // Calculate move amount dir = obj.emitDir * s; // Applies acceleration of gravity if (Info.IsPositionStyle(ParticleInfo.ParamStyles.Gravity)) { float _fact = globalGravityFactor * (obj.mass * (tempInterval * tempInterval)); obj.gravity += vGravDir * _fact; dir += obj.gravity; } obj.targetPos = obj.pos[0] + dir; obj.startPos = obj.pos[0]; obj.posInterval -= Info.PositionUpdateInterval; } // If random type if (Info.IsPositionStyle(ParticleInfo.ParamStyles.Random)) { obj.posRandomInterval -= time; if (obj.posRandomInterval <= 0.0f) { Vector3 rndVec = HelperMath.RandomVector2(); rndVec *= Info.PositionRandomFactor; obj.targetPos += rndVec; obj.posRandomInterval = Info.PositionRandomInterval; } } // Trace to position if (Info.ParticleType == ParticleInfo.ParticleObjectType.Billboard) { obj.pos[1] = obj.pos[0]; } // Position interpolate if (isInterpolate) { obj.pos[0] = Vector3.Lerp(obj.startPos, obj.targetPos, (obj.posInterval * posRinterval)); } else { obj.pos[0] = obj.targetPos; } ////////////////////////////////////////////////////////// // Scale isInterpolate = true; obj.scaleInterval += time; tempInterval = obj.scaleInterval; if (tempInterval >= Info.ScaleUpdateInterval) { int last = scaleArgCount - 1; if (Info.ScaleUpdateInterval < time) { tempInterval = obj.scaleInterval = time; isInterpolate = false; } switch (Info.ScaleFunc[last]) { case ParticleInfo.FuncType.Constant: { obj.scaleArg[last] = Info.ScaleInit[last]; } break; case ParticleInfo.FuncType.Sin: { obj.scaleArg[last] = (float)Math.Sin(MathHelper.PiOver2 * lifeTime) * Info.ScaleFactor[last]; } break; case ParticleInfo.FuncType.Cos: { obj.scaleArg[last] = (float)Math.Cos(MathHelper.PiOver2 * lifeTime) * Info.ScaleFactor[last]; } break; case ParticleInfo.FuncType.Rnd: { obj.scaleArg[last] = HelperMath.RandomNormal2(); } break; case ParticleInfo.FuncType.Table: { KeyFrameTable table = Info.ScaleTable[last]; obj.scaleArg[last] = table.GetKeyFrame(lifeTime, scaleInterpolate); } break; } // Applies random value obj.scaleArg[last] *= obj.scaleRandom; if( last == 1) obj.scaleArg[0] += obj.scaleArg[1] * tempInterval; if (Info.IsScaleStyle(ParticleInfo.ParamStyles.Clamp)) { obj.scaleArg[0] = MathHelper.Clamp(obj.scaleArg[0], Info.ScaleMin, Info.ScaleMax); } obj.targetScale = Info.ScaleMask * obj.scaleArg[0]; // back up the previous scale value obj.startScale = obj.scale; obj.scaleInterval -= Info.ScaleUpdateInterval; } if (isInterpolate) { obj.scale = Vector3.Lerp(obj.startScale, obj.targetScale, (obj.scaleInterval * scaleRinterval)); } else { obj.scale = obj.targetScale; } ////////////////////////////////////////////////////////// // Rotation if( enableRotate) { switch(Info.RotateFunc) { case ParticleInfo.FuncType.None: { obj.rotateArg = 0.0f; } break; case ParticleInfo.FuncType.Constant: { obj.rotateArg = Info.RotateInit * time; } break; case ParticleInfo.FuncType.Sin: { obj.rotateArg = (float)Math.Sin(MathHelper.PiOver2 * lifeTime) * Info.RotateFactor; } break; case ParticleInfo.FuncType.Cos: { obj.rotateArg = (float)Math.Sin(MathHelper.PiOver2 * lifeTime) * Info.RotateFactor; } break; case ParticleInfo.FuncType.Rnd: { obj.rotateArg = HelperMath.RandomNormal2(); } break; case ParticleInfo.FuncType.Table: { KeyFrameTable table = Info.RotateTable; obj.rotateArg = table.GetKeyFrame(lifeTime, KeyFrameTable.Interpolation.Lerp); } break; } obj.rotateAccm += obj.rotateArg * obj.rotateRandom; } ////////////////////////////////////////////////////////// // Color { byte r = obj.color.R; byte g = obj.color.G; byte b = obj.color.B; byte a = obj.color.A; if (!Info.IsColorStyle(ParticleInfo.ParamStyles.Random) || obj.IsState(ParticleObject.States.FirstTime)) { switch (Info.RgbFunc) { case ParticleInfo.FuncType.Constant: { r = Info.RgbInitValue.R; g = Info.RgbInitValue.G; b = Info.RgbInitValue.B; } break; case ParticleInfo.FuncType.Table: { float rt = 0.0f; if (Info.IsColorStyle( ParticleInfo.ParamStyles.Random)) { rt = HelperMath.RandomNormal(); } else { rt = lifeTime; } r = (byte)Info.Rtable.GetKeyFrame(rt, colorInterpolate); g = (byte)Info.Gtable.GetKeyFrame(rt, colorInterpolate); b = (byte)Info.Btable.GetKeyFrame(rt, colorInterpolate); } break; default: { r = 255; g = 255; b = 255; } break; } } float alpha = 255f; switch (Info.AlphaFunc) { case ParticleInfo.FuncType.Constant: alpha = (float)Info.AlphaInit; break; case ParticleInfo.FuncType.Sin: alpha = 255f * (float)Math.Sin( MathHelper.PiOver2 * lifeTime); break; case ParticleInfo.FuncType.Cos: alpha = 255f * (float)Math.Cos( MathHelper.PiOver2 * lifeTime); break; case ParticleInfo.FuncType.Table: alpha = Info.Atable.GetKeyFrame(lifeTime, colorInterpolate); break; default: alpha = 255f; break; } a = (byte)alpha; obj.color = new Color(r, g, b, a); } ////////////////////////////////////////////////////////// // TextureSequence if (textureSequence != null) { obj.textureSequenceInterval -= time; // Calculate texture sequence if( (obj.textureSequenceInterval <= 0.0f) && ((textureSequence.IsFixedFrameMode == false) || (obj.IsState( ParticleObject.States.FirstTime)))) { obj.textureSequenceInterval = textureSequence.StaticInterval; textureSequence.GetUV(obj.time, out uv1, out uv2); isUv = true; } } switch (Info.ParticleType) { case ParticleInfo.ParticleObjectType.PointSprite: { scenePointSprite.SetObjectEnable(i, true); scenePointSprite.SetCenter(i, obj.pos[0]); scenePointSprite.SetSize(i, obj.scale.X, obj.scale.Y); scenePointSprite.SetColor(i, obj.color); if (isUv) scenePointSprite.SetTextureCoord(i, uv1, uv2); } break; case ParticleInfo.ParticleObjectType.Sprite: { sceneSprite3D.SetObjectEnable(i, true); sceneSprite3D.SetCenter(i, obj.pos[0]); sceneSprite3D.SetSize(i, obj.scale.X, obj.scale.Y); sceneSprite3D.SetColor(i, obj.color); sceneSprite3D.SetRotation(i, obj.rotateAccm); if (isUv) sceneSprite3D.SetTextureCoord(i, uv1, uv2); } break; case ParticleInfo.ParticleObjectType.Billboard: { Vector3 diff = Vector3.Zero; diff = obj.pos[0] - obj.pos[1]; diff *= Info.ScaleBillboardFactor; diff += obj.pos[0]; sceneBillboard.SetUpdateType(i, true); sceneBillboard.SetStart(i, obj.pos[0]); sceneBillboard.SetEnd(i, diff); sceneBillboard.SetSize(i, obj.scale.Y); sceneBillboard.SetColor(i, obj.color); if(isUv) sceneBillboard.SetTextureCoord(i, uv1, uv2); } break; case ParticleInfo.ParticleObjectType.AnchorBillboard: { sceneBillboard.SetUpdateType(i, true); sceneBillboard.SetStart(i, obj.pos[1]); sceneBillboard.SetEnd(i, obj.pos[0]); sceneBillboard.SetSize(i, obj.scale.Y); sceneBillboard.SetColor(i, obj.color); if (isUv) sceneBillboard.SetTextureCoord(i, uv1, uv2); } break; case ParticleInfo.ParticleObjectType.Scene: { sceneMesh.Enabled = true; sceneMesh.Visible = true; // Rotation Matrix localTransform = Matrix.CreateFromAxisAngle( obj.rotateDir, obj.rotateAccm); // Scale localTransform = Helper3D.PostScale(localTransform, obj.scale); // Position localTransform.Translation = obj.pos[0]; // Set transform sceneMesh.WorldTransform = localTransform * sceneMesh.WorldTransform; } break; } } obj.state &= ~((uint)ParticleObject.States.FirstTime); } if (isStopping && aliveCount == 0) { // Particle disabled SetSceneEnable(false); } }