rotfa

Hello I'm writing a game-Engine, where at some point I have to build-up a rope which is definded by center-points an a raduis (in fact it's a curved cylinder). I have the code to build the structure. If I render it with the DrawPrimitive function, it works great.

But if I try to create a mesh out of the data (indicated with /* Problems */), the code hangs-up at some point with a Stack-Overflow message or sometime a read-write-Exception ....

Here's the code

public class cRope{

private CustomVertex.PositionNormalTextured[] _ropeVertices;
private VertexBuffer _vb;
private IndexBuffer _ib;
private int[] _indices;
private Mesh mesh;

///Create the rope --> works except the Mesh-Creation
public Mesh createRope(Device dev, Vector3[] points,  float radiusOfRope)
{
    Vector3 n;
    int circleSubdivision = 20;
    for (int i = 0; i < points.Length-1; i++)
    {
          n = Vector3.Subtract(pointsIdea, points[i+1]);
          createCircle(pointsIdea, n, radiusOfRope, circleSubdivision, (float)i % 2);
    }
    n = Vector3.Subtract(points[points.Length - 2], points[points.Length - 1]);
    createCircle(points[points.Length - 1], n, radiusOfRope, circleSubdivision, (float)points.Length - 1 % 2);
 
    _indices = newint[(points.Length - 1)*circleSubdivision* 6]; 
    int k=0;
    int faces = 0;
    for (int j = 0; j < points.Length - 1; j++)
    {
       for (int i = 0; i < circleSubdivision - 1; i++)
            {
             _indices[k] = i + j * circleSubdivision;   
            _indices[k + 1] = _indices[k] + 1;     
            _indices[k + 2] = _indices[k] + circleSubdivision;     
            _indices[k + 3] = _indices[k + 1];
            _indices[k + 4] = _indices[k + 2] + 1;
            _indices[k + 5] = _indices[k + 2];
             k += 6;
             faces += 2;
}
_indices[k] = (j + 1) * circleSubdivision - 1;
_indices[k + 1] = j * circleSubdivision;
_indices[k + 2] = _indices[k] + circleSubdivision;
_indices[k + 3] = _indices[k + 1];
_indices[k + 4] = _indices[k + 1] + circleSubdivision;
_indices[k + 5] = _indices[k + 2];
k += 6;
faces += 2;
    }       
 
/**********   PROBLEMSSSS  **********************/

mesh = newMesh(faces, _ropeVertices.Length, MeshFlags.Dynamic,  
            CustomVertex.PositionNormalTextured.Format, dev);
   
    AttributeRange[] attributeRange = newAttributeRange[1];
    attributeRange[0].AttributeId = 0;
     attributeRange[0].FaceStart = 0;
    attributeRange[0].FaceCount = faces;
    attributeRange[0].VertexStart = 0;
    attributeRange[0].VertexCount = _ropeVertices.Length;   
    mesh.SetAttributeTable(attributeRange);
   
    mesh.VertexBuffer.SetData(_ropeVertices, 0, LockFlags.None);
    mesh.IndexBuffer.SetData(_indices, 0, LockFlags.None);                     

    return mesh;
}
 
//create a circle in the place defined by a Point and a Normal to the place, subdivide the circle and return the
//Points
private void createCircle(Vector3 center, Vector3 normal, float radius, int subdivisions, float texturePosition)
{
    float arcus_increment = (float)(2.0 * Math.PI /subdivisions); //cylinder angular increment
    float tu_increment = (float)(1.0 / (subdivisions)); //texture horiz. increment
    Vector3 v = newVector3();   
    _ropeVertices = incArray(_ropeVertices,subdivisions);
   
    int insertPosition = _ropeVertices.Length - subdivisions;
 
    Vector3 x = newVector3(normal.Y, -normal.X, 0);
    if (x.X == 0 && x.Y == 0 && x.Z == 0)
    {
x = newVector3(0, normal.Z, -normal.Y);
    }
    Vector3 y = newVector3(normal.Z, 0, -normal.X);
    if (y.X == 0 && y.Y == 0 && y.Z == 0)
    {
y = newVector3(0, normal.Z, -normal.Y);
    }
    x.Normalize();
    y.Normalize();
    if (y.Z > 0)
    {
y.X *= -1;
y.Z *= -1;
    }
    for (int i = 0; i < subdivisions; i++)
    {
float arcus = i * arcus_increment;
v = Vector3.Multiply(x, radius * (float)Math.Cos(arcus)) + Vector3.Multiply(y, radius * (float)Math.Sin(arcus));
v += center;
 
//Point
_ropeVertices[insertPosition + i].Position = v;
 
//Normale
v.Y = 0;  
_ropeVertices[insertPosition + i].Normal = v;
 
//Texture
 _ropeVertices[insertPosition + i].Tv = i * tu_increment;
 _ropeVertices[insertPosition + i].Tu = texturePosition;
    }
}
 
private CustomVertex.PositionNormalTextured[] incArray(CustomVertex.PositionNormalTextured[] srcArray, int numItems)
{
    if (srcArray == null)
    {
return new CustomVertex.PositionNormalTextured[numItems];
    }
    else
    {
CustomVertex .PositionNormalTextured[] newArray = newCustomVertex.PositionNormalTextured[srcArray.Length + numItems];
Array .Copy(srcArray, newArray, srcArray.Length);
return newArray;
    }
}



Re: Game Technologies: Graphics Create Mesh causes Stack Overflow oder Read/Write Exception

rotfa

Hi

After a night of debugging I found the error, in case somebody should get the same error once I post the solution to it here.

You have to set the attributes for each face AND !!!! lock the buffers.

I replaced the code, so that I immediateley write into the Vertex- and Indexbuffers which works great.

Here's the difference in the first function:

mesh = new Mesh((points.Length - 1) * circleSubdivision * 2, _ropeVertices.Length, 0, CustomVertex.PositionNormalTextured.Format, dev);
_indices = mesh.LockIndexBuffer(
typeof(short), LockFlags.None, (points.Length - 1) * circleSubdivision * 2 * 3) as short[];
int k = 0;
int faces = 0;
for (short j = 0; j < points.Length - 1; j++)
{
for (short i = 0; i < circleSubdivision - 1; i++)
{
_indices[k] = (
short)(i + j * circleSubdivision); // i +j *circleSubdivision
_indices[k + 1] = (short)(_indices[k] + 1); // i +1 + j*circleSubdivision
_indices[k + 2] = (short)(_indices[k] + circleSubdivision); // i + circleSubdivision + j*circleSubdivision
_indices[k + 3] = (short)(_indices[k + 1]); // i + 1 + j*circleSubdivision
_indices[k + 4] = (short)(_indices[k + 2] + 1); // i + 1 + circleSubdivision + j*circleSubdivision
_indices[k + 5] = (short)(_indices[k + 2]); // i + circleSubdivision + j*circleSubdivision
k += 6;
faces += 2;
}
_indices[k] = (
short)((j + 1) * circleSubdivision - 1);
_indices[k + 1] = (
short)(j * circleSubdivision);
_indices[k + 2] = (
short)(_indices[k] + circleSubdivision);
_indices[k + 3] = (
short)(_indices[k + 1]);
_indices[k + 4] = (
short)(_indices[k + 1] + circleSubdivision);
_indices[k + 5] = (
short)(_indices[k + 2]);
k += 6;
faces += 2;
}

mesh.UnlockIndexBuffer();
int[] attributes = mesh.LockAttributeBufferArray(LockFlags.None);
for (int i = 0; i < faces; i++)
attributesIdea = 0;
mesh.UnlockAttributeBuffer(attributes);

CustomVertex.PositionNormalTextured[] vb= mesh.LockVertexBuffer(typeof(CustomVertex.PositionNormalTextured), LockFlags.None, _ropeVertices.Length) as CustomVertex.PositionNormalTextured[];
for (int i = 0; i < _ropeVertices.Length; i++)
vb.SetValue(_ropeVerticesIdea, i);
mesh.UnlockVertexBuffer();