Spectralle
Spectralle

Reputation: 69

Making a hollow voxel cone

I'm trying to create a voxel-style cone shape in C#. I've got the cone building using cubes, but can't work out how to only build the outer layer (make it hollow) rather than build a solid cone as shown in the pic.

voxel cone. The code so far (Edited from someone else's script)

// Create a cone made of cubes. Can be called at runtime
public void MakeVoxelCone()
{
    for (int currentLength = 0; currentLength < maxLength; currentLength++)
        MakeNewLayer(currentLength);
}

// Make a new layer of cubes on the cone
private void MakeNewLayer(int currentLength)
{
    center = new Vector3(0, currentLength, 0);
    for (int x = -currentLength; x < currentLength; x++)
    {
        for (int z = -currentLength; z < currentLength; z++)
        {
            // Set position to spawn cube
            Vector3 pos = new Vector3(x, currentLength, z);

            // The distance to the center of the cone at currentLength point
            float distanceToMiddle = Vector3.Distance(pos, center);

            // Create another layer of the hollow cone
            if (distanceToMiddle < currentLength)
            {
                // Add all cubes to a List array
                Cubes.Add(MakeCube(pos));
            }
        }
    }
}

// Create the cube and set its properties
private GameObject MakeCube(Vector3 position)
{
    GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
    cube.GetComponent<Renderer>().material.color = Color.blue;
    if (!AddCollider)
        Destroy(cube.GetComponent<BoxCollider>());
    cube.transform.position = position;
    cube.transform.parent = transform;
    cube.name = "cube [" + position.y + "-" + position.x + "," + position.z + "]";

    return cube;
}

I think its probably simple, but cant figure it out. Maybe something about the if (distanceToMiddle < currentLength) part, but swapping < for == breaks the whole shape.

@Jax297 >= (currentLength-1) Closer, but not correct just yet. Now its a pyramid with a cone cut out. enter image description here

Upvotes: 3

Views: 439

Answers (2)

user14492
user14492

Reputation: 2234

If you want to create a "empty" cone. Try to describe that shape in English first.

Create a circle at height going from 0...h with increasing radius for each step from 0..r

So now you need to find equation of a circle (should take you back to HS trig): sin(theta)^2 + cos(theta)^2 = radius:

cicle

Now you want to create this circle while increasing the height.

This will create only the empty cone you wish.

Here's an quick implementation (adjust as needed):

    public List<GameObject> instantiatedObjects = new List<GameObject>();
    public GameObject rootParent;
    public int numOfRows = 10;
    public int incrementPerRow = 4;
    public float radiusStep = 0.5f;
    public float height = 5;
    [Button]
    public void CreateVoxelCone()
    {
        // first one. root object.
        rootParent = GameObject.CreatePrimitive(PrimitiveType.Cube);
        rootParent.name = "Pivot";
        rootParent.transform.position = Vector3.zero;
        var itemsForThisRow = incrementPerRow;
        var heightStep = height / numOfRows;
        // for each row...
        for (int i = 0; i < numOfRows; i++)
        {
            // create items in a circle
            var radianStep = Mathf.PI * 2 / itemsForThisRow;
            for (float j = 0; j < Mathf.PI*2; j=j+radianStep)
            {
                var newPosition = new Vector3(Mathf.Cos(j) * radiusStep * i, heightStep * i, Mathf.Sin(j) * radiusStep*i);
                var point = GameObject.CreatePrimitive(PrimitiveType.Cube);
                point.name = ($"Row: {i}, {j}");
                point.transform.SetParent(rootParent.transform);
                point.transform.localPosition = newPosition;
                instantiatedObjects.Add(point);
            }

            itemsForThisRow += incrementPerRow;
        }
    }

    [Button]
    public void CleanUp()
    {
        DestroyImmediate(rootParent);
    }

Result Coneempty cone

Upvotes: 0

Bacon
Bacon

Reputation: 483

assuming your currentlength is the outer diameter you have to introduce a thickness vareable and compare to currentleght - thickness, so there is a inner diameter to be kept free

(currentLength - thickness) < distanceToMiddle && distanceToMiddle < currentLength 

Upvotes: 3

Related Questions