-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSphere.cs
More file actions
115 lines (103 loc) · 4.73 KB
/
Sphere.cs
File metadata and controls
115 lines (103 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Boatanator
{
public class Sphere
{
public VertexBuffer vertexBuffer;
public IndexBuffer indexBuffer;
public BasicEffect effect;
Sphere( ) { }
public static Sphere Create( GraphicsDevice device )
{
return Create( device, 15, 7, v => v );
}
public static Sphere CreateNormalTextured( GraphicsDevice device, int slices, int stacks )
{
return Create( device, slices, stacks, v => v );
}
public static Sphere CreateTextured( GraphicsDevice device, int slices, int stacks )
{
return Create( device, slices, stacks, v => new VertexPositionTexture( v.Position, v.TextureCoordinate ) );
}
public static Sphere Create<T>( GraphicsDevice device, int slices, int stacks, Func<VertexPositionNormalTexture, T> createVertexCallback ) where T : struct
{
return Create( device, slices, stacks, 0, 0, -MathHelper.PiOver2, MathHelper.PiOver2, createVertexCallback, true );
}
public static Sphere CreateHalf<T>( GraphicsDevice device, int slices, int stacks, Func<VertexPositionNormalTexture, T> createVertexCallback ) where T : struct
{
return Create( device, slices, stacks, 0, 0, 0, MathHelper.PiOver2, createVertexCallback, true );
}
public static Sphere Create<T>( GraphicsDevice device, int slices, int stacks,
float sliceAngle1, float sliceAngle2, float stackAngle1, float stackAngle2,
Func<VertexPositionNormalTexture, T> createVertexCallback, bool insideVisible ) where T : struct
{
if ( slices < 3 || stacks < 3 || slices > ushort.MaxValue || stacks > ushort.MaxValue || ( slices + 1 ) * ( stacks + 1 ) > ushort.MaxValue )
throw new ArgumentOutOfRangeException( "Sphere does not support 64K+ vertices" );
if ( sliceAngle1 > sliceAngle2 || stackAngle1 >= stackAngle2 )
throw new ArgumentOutOfRangeException( "Angles are wrong" );
var vpnt = new T[ ( slices + 1 ) * ( stacks + 1 ) ];
float phi, theta;
float dphi = ( stackAngle2 - stackAngle1 ) / stacks;
float dtheta = sliceAngle2 == sliceAngle1 ? MathHelper.TwoPi / slices : ( sliceAngle2 - sliceAngle1 ) / slices;
float x, y, z, sc;
int index = 0;
for ( int stack = 0; stack <= stacks; stack++ )
{
phi = stack == stacks ? stackAngle2 : stackAngle1 + stack * dphi;
y = (float)Math.Sin( phi );
sc = -(float)Math.Cos( phi );
for ( int slice = 0; slice <= slices; slice++ )
{
theta = slice == slices ? sliceAngle2 : sliceAngle1 + slice * dtheta;
x = sc * (float)Math.Sin( theta );
z = sc * (float)Math.Cos( theta );
vpnt[ index++ ] = createVertexCallback( new VertexPositionNormalTexture( new Vector3( x, y, z ), new Vector3( x, y, z ),
new Vector2( (float)slice / (float)slices, (float)stack / (float)stacks ) ) );
}
}
var indices = new ushort[ slices * stacks * 6 ];
index = 0;
int k = slices + 1;
for ( int stack = 0; stack < stacks; stack++ )
{
for ( int slice = 0; slice < slices; slice++ )
{
indices[ index++ ] = (ushort)( ( stack + 0 ) * k + slice );
indices[ index++ ] = insideVisible ? (ushort)( ( stack + 0 ) * k + slice + 1 ) : (ushort)( ( stack + 1 ) * k + slice + 0 );
indices[ index++ ] = insideVisible ? (ushort)( ( stack + 1 ) * k + slice + 0 ) : (ushort)( ( stack + 0 ) * k + slice + 1 );
indices[ index++ ] = (ushort)( ( stack + 0 ) * k + slice + 1 );
indices[ index++ ] = insideVisible ? (ushort)( ( stack + 1 ) * k + slice + 1 ) : (ushort)( ( stack + 1 ) * k + slice );
indices[ index++ ] = insideVisible ? (ushort)( ( stack + 1 ) * k + slice ) : (ushort)( ( stack + 1 ) * k + slice + 1 );
}
}
var ret = new Sphere( );
ret.vertexBuffer = new VertexBuffer( device, typeof( T ), vpnt.Length, BufferUsage.WriteOnly );
ret.vertexBuffer.SetData( vpnt );
ret.indexBuffer = new IndexBuffer( device, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly );
ret.indexBuffer.SetData( indices );
ret.effect = new BasicEffect( device );
return ret;
}
public int Draw( Matrix view, Matrix projection )
{
var device = vertexBuffer.GraphicsDevice;
device.SetVertexBuffer( vertexBuffer );
device.Indices = indexBuffer;
effect.View = view;
effect.Projection = projection;
effect.CurrentTechnique.Passes[ 0 ].Apply( );
device.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3 );
return vertexBuffer.VertexCount;
}
public int DrawNoShader( )
{
var device = vertexBuffer.GraphicsDevice;
device.SetVertexBuffer( vertexBuffer );
device.Indices = indexBuffer;
device.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3 );
return vertexBuffer.VertexCount;
}
}
}