Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
GeometricMultiTexcoordPrimitive.Cylinder.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 
6 using SiliconStudio.Core;
7 using SiliconStudio.Core.Mathematics;
8 
9 namespace SiliconStudio.Paradox.Graphics
10 {
11  public partial class GeometricMultiTexcoordPrimitive
12  {
13  /// <summary>
14  /// A Cylinder primitive.
15  /// </summary>
16  public struct Cylinder
17  {
18  // Helper computes a point on a unit circle, aligned to the x/z plane and centered on the origin.
19  private static Vector3 GetCircleVector(int i, int tessellation)
20  {
21  var angle = (float)(i * 2.0 * Math.PI / tessellation);
22  var dx = (float)Math.Sin(angle);
23  var dz = (float)Math.Cos(angle);
24 
25  return new Vector3(dx, 0, dz);
26  }
27 
28  // Helper creates a triangle fan to close the end of a cylinder.
29  private static void CreateCylinderCap(List<VertexPositionNormalTangentMultiTexture> vertices, List<int> indices, int tessellation, float height, float radius, bool isTop)
30  {
31  // Create cap indices.
32  for (int i = 0; i < tessellation - 2; i++)
33  {
34  int i1 = (i + 1) % tessellation;
35  int i2 = (i + 2) % tessellation;
36 
37  if (isTop)
38  {
39  Utilities.Swap(ref i1, ref i2);
40  }
41 
42  int vbase = vertices.Count;
43  indices.Add(vbase);
44  indices.Add(vbase + i1);
45  indices.Add(vbase + i2);
46  }
47 
48  // Which end of the cylinder is this?
49  var normal = Vector3.UnitY;
50  var textureScale = new Vector2(-0.5f);
51 
52  if (!isTop)
53  {
54  normal = -normal;
55  textureScale.X = -textureScale.X;
56  }
57 
58  // Create cap vertices.
59  for (int i = 0; i < tessellation; i++)
60  {
61  var circleVector = GetCircleVector(i, tessellation);
62  var position = (circleVector * radius) + (normal * height);
63  var textureCoordinate = new Vector2(circleVector.X * textureScale.X + 0.5f, circleVector.Z * textureScale.Y + 0.5f);
64 
65  vertices.Add(new VertexPositionNormalTangentMultiTexture(position, normal, new Vector4(isTop ? -1 : 1, 0, 0, 0), textureCoordinate));
66  }
67  }
68 
69  /// <summary>
70  /// Creates a cylinder primitive.
71  /// </summary>
72  /// <param name="device">The device.</param>
73  /// <param name="height">The height.</param>
74  /// <param name="diameter">The diameter.</param>
75  /// <param name="tessellation">The tessellation.</param>
76  /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is false.</param>
77  /// <returns>A cylinder primitive.</returns>
78  /// <exception cref="System.ArgumentOutOfRangeException">tessellation;tessellation must be &gt;= 3</exception>
79  public static GeometricMultiTexcoordPrimitive New(GraphicsDevice device, float height = 1.0f, float diameter = 1.0f, int tessellation = 32, bool toLeftHanded = false)
80  {
81  // Create the primitive object.
82  return new GeometricMultiTexcoordPrimitive(device, New(height, diameter, tessellation, toLeftHanded));
83  }
84 
85  /// <summary>
86  /// Creates a cylinder primitive.
87  /// </summary>
88  /// <param name="height">The height.</param>
89  /// <param name="diameter">The diameter.</param>
90  /// <param name="tessellation">The tessellation.</param>
91  /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is false.</param>
92  /// <returns>A cylinder primitive.</returns>
93  /// <exception cref="System.ArgumentOutOfRangeException">tessellation;tessellation must be &gt;= 3</exception>
94  public static GeometricMeshData<VertexPositionNormalTangentMultiTexture> New(float height = 1.0f, float diameter = 1.0f, int tessellation = 32, bool toLeftHanded = false)
95  {
96  if (tessellation < 3)
97  throw new ArgumentOutOfRangeException("tessellation", @"tessellation must be >= 3");
98 
99  var vertices = new List<VertexPositionNormalTangentMultiTexture>();
100  var indices = new List<int>();
101 
102  height /= 2;
103 
104  var topOffset = Vector3.UnitY * height;
105 
106  float radius = diameter / 2;
107  int stride = tessellation + 1;
108 
109  // Create a ring of triangles around the outside of the cylinder.
110  for (int i = 0; i <= tessellation; i++)
111  {
112  var normal = GetCircleVector(i, tessellation);
113 
114  var sideOffset = normal * radius;
115 
116  var textureCoordinate = new Vector2((float)i / tessellation, 0);
117 
118  var tangent = new Vector4(normal.Z, 0, -normal.X, 0); // Y ^ normal
119  vertices.Add(new VertexPositionNormalTangentMultiTexture(sideOffset + topOffset, normal, tangent, textureCoordinate));
120  vertices.Add(new VertexPositionNormalTangentMultiTexture(sideOffset - topOffset, normal, tangent, textureCoordinate + Vector2.UnitY));
121 
122  indices.Add(i * 2);
123  indices.Add((i * 2 + 2) % (stride * 2));
124  indices.Add(i * 2 + 1);
125 
126  indices.Add(i * 2 + 1);
127  indices.Add((i * 2 + 2) % (stride * 2));
128  indices.Add((i * 2 + 3) % (stride * 2));
129  }
130 
131  // Create flat triangle fan caps to seal the top and bottom.
132  CreateCylinderCap(vertices, indices, tessellation, height, radius, true);
133  CreateCylinderCap(vertices, indices, tessellation, height, radius, false);
134 
135  // Create the primitive object.
136  return new GeometricMeshData<VertexPositionNormalTangentMultiTexture>(vertices.ToArray(), indices.ToArray(), toLeftHanded) { Name = "Cylinder" };
137  }
138  }
139  }
140 }
static GeometricMultiTexcoordPrimitive New(GraphicsDevice device, float height=1.0f, float diameter=1.0f, int tessellation=32, bool toLeftHanded=false)
Creates a cylinder primitive.
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
Represents a two dimensional mathematical vector.
Definition: Vector2.cs:42
static readonly Vector2 UnitY
The Y unit SiliconStudio.Core.Mathematics.Vector2 (0, 1).
Definition: Vector2.cs:62
A geometric primitive. Use Sphere to learn how to use it.
Describes a custom vertex format structure that contains position, color and 10 texture coordinates i...
Represents a three dimensional mathematical vector.
Definition: Vector3.cs:42
Performs primitive-based rendering, creates resources, handles system-level variables, adjusts gamma ramp levels, and creates shaders. See The+GraphicsDevice+class to learn more about the class.
Represents a four dimensional mathematical vector.
Definition: Vector4.cs:42
SiliconStudio.Core.Mathematics.Vector3 Vector3
static GeometricMeshData< VertexPositionNormalTangentMultiTexture > New(float height=1.0f, float diameter=1.0f, int tessellation=32, bool toLeftHanded=false)
Creates a cylinder primitive.