Extending nodes

Oct 21, 2009 at 7:22 PM

I have tried to create an annular ring from code, analogous to the code found in Box.cs.  I receive an error during

GeometryContext.Render(viewport, view, projection, World); in Geometry.

The error is:

{System.NullReferenceException: Object reference not set to an instance of an object.
   at Balder.Core.Geometries.Geometry.Render(IViewport viewport, Matrix view, Matrix projection)
   at Balder.Core.Scene.Render(IViewport viewport, Matrix view, Matrix projection)
   at Balder.Core.Game.OnRender()
   at Balder.Core.Game.<OnLoaded>b__7(Object s, EventArgs e)
   at System.EventHandler.Invoke(Object sender, EventArgs e)
   at Balder.Silverlight.Services.Display.OnDraw()
   at Balder.Core.SoftwareRendering.FrameBufferRender.Invoke()
   at Balder.Silverlight.SoftwareRendering.FrameBuffer.RenderThread()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()}

I am new at 3D modeling and, from what I can see, I correctly fill vertices and create my faces.  But am not certain what happens to cause this error.

Any help would be appreciated. 

My code is:

using System.Collections.Generic;
using Balder.Core.Geometries;
using Balder.Core.Services;

namespace Balder.Silverlight.TestApp
{
    public class AnnularRing: Geometry
 {
        private Geometry _geometry;

  public AnnularRing(IContentManager contentManager, float innerRadius, float outerRadius, int slices)
  {
            ContentManager = contentManager;
            _geometry = ContentManager.CreateAssetPart<Geometry>();
            InnerRadius = innerRadius;
            OuterRadius = outerRadius;
            Slices = slices;

   PrepareVertices();
   PrepareFaces();
  }

  public float InnerRadius { get; private set; }
  public float OuterRadius { get; private set; }
  public int Slices { get; private set; }
        public IContentManager ContentManager { get; private set; }

  private void PrepareVertices()
  {
           
            Vertex[] vertices = new Vertex[2 * Slices];

            _geometry.GeometryContext.AllocateVertices(2 * Slices);

            for (int i = 0; i < Slices; i++)
            {
                float innerX = (float)(InnerRadius * System.Math.Sin(2 * i * System.Math.PI / Slices));
                float innerY = (float)(InnerRadius * System.Math.Cos(2 * i * System.Math.PI / Slices));

                _geometry.GeometryContext.SetVertex(i, new Vertex(innerX, innerY, 0));

                float outerX = (float)(InnerRadius * System.Math.Sin(2 * i * System.Math.PI / Slices));
                float outerY = (float)(InnerRadius * System.Math.Cos(2 * i * System.Math.PI / Slices));
                _geometry.GeometryContext.SetVertex(i + Slices, new Vertex(innerX, innerY, 0));
            }
  }

  private void PrepareFaces()
  {
            _geometry.GeometryContext.AllocateFaces(2 * Slices);

            int offset = 0;
            for (int slice = 0; slice < Slices; slice++)
            {
                if (Slices + slice + 1 < 2 * Slices)
                {
                    _geometry.GeometryContext.SetFace(offset, new Face(slice, Slices + slice, Slices + slice + 1));
                    _geometry.GeometryContext.SetFace(offset + 1, new Face(Slices + slice + 1, slice + 1, slice));
                }
                else
                {
                    _geometry.GeometryContext.SetFace(offset, new Face(slice, Slices + slice, 0));
                    _geometry.GeometryContext.SetFace(offset + 1, new Face(0, slice + 1, slice));
                }
                offset += 2;
            }
       }
   }
}

Coordinator
Oct 22, 2009 at 6:10 AM

I'll have a look at it later today and see what is causing it. 

As a result, I'll see if I can create a tutorial for things like this as well. 

 

Coordinator
Oct 22, 2009 at 9:21 PM
Edited Oct 22, 2009 at 9:23 PM

Hi,

I've looked it over, you need to inherit from RenderableNode and implement Render. I need to revise the API on this a bit, its a bit too hard to get this right. Anyhow, I wasn't able to get anything onto the screen even though I fixed that, but I didn't spend much time in your code trying to figure out what that might be. 

 

	public class AnnularRing : RenderableNode
	{
		private Geometry _geometry;

		public AnnularRing(IContentManager contentManager, float innerRadius, float outerRadius, int slices)
		{
			ContentManager = contentManager;
			_geometry = ContentManager.CreateAssetPart<Geometry>();
			InnerRadius = innerRadius;
			OuterRadius = outerRadius;
			Slices = slices;

			PrepareVertices();
			PrepareFaces();
		}

		public float InnerRadius { get; private set; }
		public float OuterRadius { get; private set; }
		public int Slices { get; private set; }
		public IContentManager ContentManager { get; private set; }

		private void PrepareVertices()
		{
			Vertex[] vertices = new Vertex[2 * Slices];

			_geometry.GeometryContext.AllocateVertices(2 * Slices);

			for (int i = 0; i < Slices; i++)
			{
				float innerX = (float)(InnerRadius * System.Math.Sin(2 * i * System.Math.PI / Slices));
				float innerY = (float)(InnerRadius * System.Math.Cos(2 * i * System.Math.PI / Slices));

				_geometry.GeometryContext.SetVertex(i, new Vertex(innerX, innerY, 0));

				float outerX = (float)(InnerRadius * System.Math.Sin(2 * i * System.Math.PI / Slices));
				float outerY = (float)(InnerRadius * System.Math.Cos(2 * i * System.Math.PI / Slices));
				_geometry.GeometryContext.SetVertex(i + Slices, new Vertex(innerX, innerY, 0));
			}
		}

		private void PrepareFaces()
		{
			_geometry.GeometryContext.AllocateFaces(2 * Slices);

			int offset = 0;
			for (int slice = 0; slice < Slices; slice++)
			{
				if (Slices + slice + 1 < 2 * Slices)
				{
					_geometry.GeometryContext.SetFace(offset, new Face(slice, Slices + slice, Slices + slice + 1));
					_geometry.GeometryContext.SetFace(offset + 1, new Face(Slices + slice + 1, slice + 1, slice));
				}
				else
				{
					_geometry.GeometryContext.SetFace(offset, new Face(slice, Slices + slice, 0));
					_geometry.GeometryContext.SetFace(offset + 1, new Face(0, slice + 1, slice));
				}
				offset += 2;
			}
		}

		public override void Render(IViewport viewport, Matrix view, Matrix projection)
		{
			_geometry.GeometryContext.Render(viewport,view,projection,World);
		}
	}