Jump to content
  • Advertisement
Sign in to follow this  
thehan

SOLVED: REALLY strange bug: Drawindexedprimitive throws NullReferenceException

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

EDIT: I solved this. The error was in my call to drawindexedprimitive where I passed the number of indices instead of the number of vertices. Really hard to find this error though, cause I was so very convinced it was a bug in DX9 :-/. But after 26 hours and 34 minutes of "nonstop" debugging I finally found it. ------------------------------ I'm having a really strange bug in my Managed DX9c C# program. I have three pairs of vertexbuffer/indexbuffer which are generated by my program. I will try to explain it but feel free to ask specific questions on the explanation, which is quite complicated. Basically each vertexbuffer/indexbuffer describes a cylinder's mantle, and the user is allowed to specify how "sides" the cylinder should have (for example if the user specifies 4 it's going to be a box). Now I'm generating three different cylinders (with different tapering) using my own code. The vertexbuffer is generated correctly because I can draw all vertices using drawprimitive to draw them as a pointlist. Each of the cylinders also gets its own indexbuffer. Now for debug reasons I simplified the program to generate three cylinders with the same number of sides which basically means that all three index buffers have the same indices. I also checked the Arrays (via a log file) that I put into the indexbuffers. When rendering the three cylinders, two of them generates a nullreferenceexception in Drawindexedprimitives, and the other doesn't (This appears when the number of sides is about 4000, because I'm testing the limits and if I divide the cylinder into more than one vertical segment the number of vertices can reach this number without the detail of the cylinder model being that high). Because all three cylinders have the same number of vertices and the same indices I do not think it's a simple "MAX Number of Vertices" to draw in drawindexedbuffer. But I DO believe that it can have something to do with the memory of the vertex and index buffers. I didn't explicitly check that the generated indices were copied to the indexbuffer, but the SetData method throws no exception. However if I run the program in release mode instead of debug mode one of the previously erroneous cylinders gets drawn and there is now only one cylinder that throws the nullreferenceexception. Could it be a bug in DX/.NET FramWork??? At some strange occations the program also generates this error if the number of sides and segments are low. That is why the problem bothers me. I want the user to be able to set a continuous range of LevelOfDetail (sides and segments). Now to the question: Is there anyone who had a similar problem? (I know that my variables are created and initialized, so its not a common nullreference problem) My only conclusion is that there must be something wrong with my indexbuffers beacause the vertex buffers are fine, OR a memory problem, OR something wrong with DX/.NET Framework (Is there an update that fixes this kind of error). Another thing i thought of would be that the triangle at some point will have zero size (eg. two or more of the vertices get the same coordinate). Would this generate such an error? What could be wrong? Please help me!!! Thanks! (The description of my program is very simplified above, because I'm really generating tree's and the cylinders are the stems. I just want to visualize the generation and with different LOD (eg. number of sides) it works or works not.) [Edited by - thehan on July 26, 2005 9:00:29 PM]

Share this post


Link to post
Share on other sites
Advertisement
Could you please paste your code for creating the cylinders (vb's and ib's) and also the rendering code, I feel it's much simpler to visualize the problem and detect problem when the code is pasted.

Thanks :)

Share this post


Link to post
Share on other sites
Of course (hope I do it right = first time I paste code here).

Code for generating VB:


//Setup nodes
//Base
_base.Verts = new CustomVertex.PositionNormalColored[parset.nHorizLOD];
//Dummies (middle nodes)
if(_dummies != null)
foreach(cNode dummy in _dummies)
{
dummy.Verts = new CustomVertex.PositionNormalColored[parset.nHorizLOD];
}
//Top
_top.Verts = new CustomVertex.PositionNormalColored[parset.nHorizLOD];


//Fill in information
double step = 2.0*Math.PI/parset.nHorizLOD;

for(int i=0;i<parset.nHorizLOD;i++)
{
_base.Verts.X = _base.Radius*(float)Math.Cos(i*step);
_base.Verts.Y = _base.Radius*(float)Math.Sin(i*step);
_base.Verts.Z = _base.Z;
_base.Verts.Color = Color.Blue.ToArgb();
_base.Verts.Nx = _base.Verts.X;
_base.Verts.Ny = _base.Verts.Y;
_base.Verts.Nz = 0;
_base.Verts.Normal = Vector3.Normalize(_base.Verts.Normal);

if(_dummies != null)
foreach(cNode dummy in _dummies)
{
dummy.Verts.X = dummy.Radius*(float)Math.Cos(i*step);
dummy.Verts.Y = dummy.Radius*(float)Math.Sin(i*step);
dummy.Verts.Z = dummy.Z;
dummy.Verts.Color = Color.White.ToArgb();
dummy.Verts.Nx = dummy.Verts.X;
dummy.Verts.Ny = dummy.Verts.Y;
dummy.Verts.Nz = 0;
dummy.Verts.Normal = Vector3.Normalize(dummy.Verts.Normal);
}

_top.Verts.X = _top.Radius*(float)Math.Cos(i*step);
_top.Verts.Y = _top.Radius*(float)Math.Sin(i*step);
_top.Verts.Z = _top.Z;
_top.Verts.Color = Color.Green.ToArgb();
_top.Verts.Nx = _top.Verts.X;
_top.Verts.Ny = _top.Verts.Y;
_top.Verts.Nz = 0;
_top.Verts.Normal = Vector3.Normalize(_top.Verts.Normal);
}

_vb = new VertexBuffer(typeof(CustomVertex.PositionNormalColored),(((_dummies==null)?0:_dummies.Length)+2) * parset.nHorizLOD, dev, Usage.WriteOnly, CustomVertex.PositionNormalColored.Format, Pool.Managed);

GraphicsStream stream = _vb.Lock(0,0,0);

stream.Write(_basecopy.Verts);

if(_dummies != null)
foreach(cNode dummy in _dummies)
stream.Write(dummy.Verts);

stream.Write(_top.Verts);

_vb.Unlock();




As i said, the vertexbuffer is correctly set up because I can draw the vertices as points, and they are all as they should be.

A small comment for understanding the above code: I use a nodeclass to hold the vertex ARRAYS. _base, _dummies[], and _top are the cylinders base vertices, middle segment (dummy) vertices and top vertices respectively. A node also contains information about radius at that level. The number of vertices used to form the "circle" of each node is in parset.nHorizLOD. There may be a different number of dummies depending on another LOD parameter.

Code for generating IB:


int[] indices = new int[6 * (1+ ((_dummies==null)?0:_dummies.Length) ) * parset.nHorizLOD];

int HL = parset.nHorizLOD;
int index = 0;

for(int j=0;j<(1+((_dummies==null)?0:_dummies.Length));j++)
{
for(int i=0;i<HL;i++)
{
if(i == 0)
{
indices[index+0] = 0 + j*HL;
indices[index+1] = HL + j*HL;
indices[index+2] = 2*HL-1 + j*HL;
indices[index+3] = HL-1 + j*HL;
indices[index+4] = 0 + j*HL;
indices[index+5] = 2*HL-1 + j*HL;
}
else
{
indices[index+0] = i + j*HL;
indices[index+1] = i+HL + j*HL;
indices[index+2] = i+HL-1 + j*HL;
indices[index+3] = i-1 + j*HL;
indices[index+4] = i + j*HL;
indices[index+5] = i+HL-1 + j*HL;
}
index += 6;
}
}
cLogger.log.WriteLine("Indices:");
for(int i=0;i<indices.Length;i++)
{
cLogger.log.WriteLine("Index["+i+"] = " + indices);
}

try
{
_ib = new IndexBuffer(typeof(int), indices.Length, dev,Usage.WriteOnly,
Pool.Managed);
}
catch(Exception e)
{
cLogger.log.WriteLine("ERROR in creating index buffer");
}
try
{
_ib.SetData(indices,0,LockFlags.None);
}
catch(Exception e)
{
cLogger.log.WriteLine("ERROR in setting data to index buffer");
}




The generated indices are as expected which I can see in my log file.

Code for rendering (device states etc are set):


public void Render(Device dev,cTreeParams parset)
{
dev.VertexFormat = CustomVertex.PositionNormalColored.Format;
dev.SetStreamSource(0,_vb,0);
dev.Indices = _ib;
dev.Transform.World = _world;
try
{
//DOESn't generally work, throws exceptions sometimes
dev.DrawIndexedPrimitives(PrimitiveType.TriangleList,0,0,
6*(1+((_dummies==null)?0:_dummies.Length))*parset.nHorizLOD,
0,2*(1+((_dummies==null)?0:_dummies.Length))*parset.nHorizLOD);
}
catch(NullReferenceException e)
{
cLogger.log.WriteLine("ERROR in call to drawindexedprimitives");
}

//WORKS:
dev.DrawPrimitives(PrimitiveType.PointList,0,(((_dummies==null)?
0:_dummies.Length)+2)*_base.Verts.Length);

/* My cylinders are organized as a linked list for later animation reasons */
if(_child != null)
_child.Render(dev,parset);
}




That's pretty much it. I think there is something wrong with the indexbuffer creation so that indices isn't copied to the indexbuffer (although it doesn't generate exceptions in setdata), and thus drawindexedprimitives finds that the IB is null reference. Why else would drawprimitives work and drawindexedprimitives not? Could this be it, and in that case, what the ** am I doing wrong? (It really gives me a headache working with this sort of bugs.) Otherwise, if the indexbuffer is set, could something else cause this? The video card (I'm using a GeforceFX-level card)? DirectX (I've heard that managed directX isn't that bugfree yet)? Something else?

I hope this clearified my problem a bit more. Once again, if I draw three cylinders generated using the same code, the same number of "dummies", the same number of vertices, but with different radius'es, some of them show up and others don't depending on the LOD parameters. I tried out to draw a zero sized triangle in a new project and that worked so it cannot be a problem like that.

Plz help, thanks!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!