/// <summary> /// configures vertex color to the vertex component data /// using the billboard object. /// </summary> /// <param name="vertexData">target vertex component data</param> /// <param name="obj">source billboard object</param> /// <param name="startIndex">start index of the vertex component data</param> private static void SetBufferColor(ref VertexPositionColorTexture[] vertexData, BillboardObject obj, int startIndex) { for (int i = 0; i < 4; i++) { vertexData[startIndex + i].Color = obj.Color; } }
/// <summary> /// create billboard objects using the texture. /// </summary> /// <param name="count">billboard object count</param> /// <param name="texture">texture resource</param> /// <param name="renderingSpace">3D render space</param> /// <param name="alwaysUpdate"></param> public void Create(int count, Texture2D texture, RenderingSpace renderingSpace, bool alwaysUpdate) { this.objectCount = count; this.renderingSpace = renderingSpace; this.alwaysUpdate = alwaysUpdate; // create billboard objects. for (int i = 0; i < count; i++) { BillboardObject obj = new BillboardObject(); obj.AddUpdateType(BillboardObject.UpdateTypes.Enable); billboardList.Add(obj); } base.Create(count * vertexStride, count * indexStride, texture); }
/// <summary> /// configures texture coordinates to the vertex component data /// using the billboard object. /// </summary> /// <param name="vertexData">target vertex component data</param> /// <param name="obj">source billboard object</param> /// <param name="startIndex">start index of the vertex component data</param> /// <param name="renderingSpace">3D render space</param> private static void SetBufferTextureCoord( ref VertexPositionColorTexture[] vertexData, BillboardObject obj, int startIndex, RenderingSpace renderingSpace) { float u1 = 0.0f, v1 = 0.0f, u2 = 0.0f, v2 = 0.0f; u1 = obj.MinUV.X; v1 = obj.MinUV.Y; u2 = obj.MaxUV.X; v2 = obj.MaxUV.Y; if (renderingSpace == RenderingSpace.Screen) { float swap = v1; v1 = v2; v2 = swap; } vertexData[startIndex + 0].TextureCoordinate = new Vector2(u1, v2); vertexData[startIndex + 1].TextureCoordinate = new Vector2(u1, v1); vertexData[startIndex + 2].TextureCoordinate = new Vector2(u2, v2); vertexData[startIndex + 3].TextureCoordinate = new Vector2(u2, v1); }
/// <summary> /// configures a position vector to the vertex component data /// using the billboard object. /// </summary> /// <param name="vertexData">target vertex component data</param> /// <param name="obj">source billboard object</param> /// <param name="startIndex">start index of the vertex component data</param> /// <param name="ay">position vector</param> private static void SetBufferPosition( ref VertexPositionColorTexture[] vertexData, BillboardObject obj, int startIndex, Vector3 ay) { Vector3 by = Vector3.Zero; float cy = obj.Size * 0.5f; by = ay * cy; // [0] [1] // +-------------+ // | | // +c | // | | // +-------------+ // [2] [3] // 0 2 1 - 1 2 3 vertexData[startIndex + 0].Position = obj.Start - by; vertexData[startIndex + 1].Position = obj.End - by; vertexData[startIndex + 2].Position = obj.Start + by; vertexData[startIndex + 3].Position = obj.End + by; }
/// <summary> /// configures vertex color to the vertex component data /// using the billboard object. /// </summary> /// <param name="vertexData">target vertex component data</param> /// <param name="obj">source billboard object</param> /// <param name="startIndex">start index of the vertex component data</param> private static void SetBufferColor(ref VertexPositionColorTexture[] vertexData, BillboardObject obj, int startIndex) { for (int i = 0; i < 4; i++) vertexData[startIndex + i].Color = obj.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); }