Files
sbox-public/game/addons/tools/Code/MeshEditor/Primitives/Sphere.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

109 lines
2.8 KiB
C#

using System;
namespace Editor.MeshEditor;
[Title( "Sphere" ), Icon( "circle" )]
internal class SpherePrimitive : PrimitiveBuilder
{
[Title( "Number of sides" )]
public int NumberOfSides { get; set; } = 8;
[Hide] public Vector3 Center { get; set; }
[Hide] public Vector3 Size { get; set; }
public override void SetFromBox( BBox box )
{
Center = box.Center;
Size = box.Size;
}
public override void Build( PolygonMesh mesh )
{
//
// Build the sphere by building slices at constant angular intervals.
//
// Each slice is a ring of four-sided faces, except for the top and bottom slices,
// which are flattened cones.
//
// Unrolled, a sphere made with 5 'sides' has 25 faces and looks like this:
//
// /\ /\ /\ /\ /\
// / 0\/ 1\/ 2\/ 3\/ 4\
// | 5| 6| 7| 8| 9|
// | 10| 11| 12| 13| 14|
// | 15| 16| 17| 18| 19|
// \20/\21/\22/\23/\24/
// \/ \/ \/ \/ \/
//
var halfSize = Size / 2;
float angle = 0.0f;
float angleStep = MathF.PI / NumberOfSides;
for ( int slice = 0; slice < NumberOfSides; slice++ )
{
float angle1 = angle + angleStep;
// Make the upper polygon.
var upperPoints = new Vector3[NumberOfSides + 1];
{
for ( int i = 0; i < NumberOfSides; i++ )
{
var angle2 = i * (MathF.PI * 2.0f / NumberOfSides);
upperPoints[i] = Center + new Vector3( MathF.Sin( angle2 ), MathF.Cos( angle2 ), -1.0f ) * halfSize * MathF.Sin( angle );
}
upperPoints[NumberOfSides] = upperPoints[0];
}
// Make the lower polygon.
var lowerPoints = new Vector3[NumberOfSides + 1];
{
for ( int i = 0; i < NumberOfSides; i++ )
{
var angle2 = i * (MathF.PI * 2.0f / NumberOfSides);
lowerPoints[i] = Center + new Vector3( MathF.Sin( angle2 ), MathF.Cos( angle2 ), -1.0f ) * halfSize * MathF.Sin( angle1 );
}
lowerPoints[NumberOfSides] = lowerPoints[0];
}
float upperHeight = Center.z + halfSize.z * MathF.Cos( angle );
float lowerHeight = Center.z + halfSize.z * MathF.Cos( angle1 );
for ( int i = 0; i < NumberOfSides; i++ )
{
// Top and bottom are cones, not rings
if ( slice == 0 )
{
mesh.AddFace(
upperPoints[i + 1].WithZ( upperHeight ),
lowerPoints[i + 1].WithZ( lowerHeight ),
lowerPoints[i].WithZ( lowerHeight )
);
}
else if ( slice == NumberOfSides - 1 )
{
mesh.AddFace(
upperPoints[i].WithZ( upperHeight ),
upperPoints[i + 1].WithZ( upperHeight ),
lowerPoints[i + 1].WithZ( lowerHeight )
);
}
else
{
mesh.AddFace(
upperPoints[i].WithZ( upperHeight ),
upperPoints[i + 1].WithZ( upperHeight ),
lowerPoints[i + 1].WithZ( lowerHeight ),
lowerPoints[i].WithZ( lowerHeight )
);
}
}
angle += angleStep;
}
}
}