sgsrules's picture

poor performance using vector math library

Hi everyone, this is my first post. I''ve been coding a 3d rendering engine for VJ use using C# and OpenGL. Originally the project started in Java/jogl but i recently ported everything to C#. In java i was using the java vecmath library which worked great but now that i'm coding in c# i need a new library that will handle vector and matrix math. After some searching i came across the OpenTK.Math library which does everything i need but i've been having some serious performance issues. One test i ran in java was running at 60fps, the same application in C# was running at 20fps. After some testing i came to the conclusion that the bottleneck was happening in my math routines. I've read good things about the OpenTK math library and one of the benchmarks i saw stated that it was pretty fast, so i'm sure i'm not implementing it right. i think the problem is that im not passing things by reference so it's making a lot of extra copies. If someone could give me some pointers i'de greatly appreciate it. Here's some sample code i wrote a while back, it basically draws a 3d arrow that bends along a path. i'm only using this as a test since it uses a lot of vector and matrix math. I'm only interested in optimizing the math functions, everything is written in immediate mode no vbos etc i know how to implement vbos and could write better code so please don't point it out :P i just need help with the openTK.math calls.

TIA
Stephen

public class Arrow
{
int count;
float Size;
float scl = 1;
Vector3[] pos;
Vector3[] square = new Vector3[4];
Vector3 acl = new Vector3();
Vector3[] vel;
Vector3 up = new Vector3(1, 1, 1);
Vector3 vx = new Vector3();
Vector3 vy = new Vector3();
Vector3 vz = new Vector3();
Vector3 anchor;

public Arrow(float _Size)
{
Size = _Size;
count = 70;
pos = new Vector3[count];
vel = new Vector3[count];
up.Normalize();
square[0] = new Vector3(-Size, -Size, 0);
square[1] = new Vector3(Size, -Size, 0);
square[2] = new Vector3(Size, Size, 0);
square[3] = new Vector3(-Size, Size, 0);
for (int i = 0; i < count; i++)
{
pos[i] = new Vector3();
vel[i] = new Vector3();
}

}

public void draw(Vector3 _anchor, float _r, float _g, float _b, float _scl, int _length, bool _tip)
{
anchor = new Vector3(_anchor);
Gl.glColor4f(_r, _g, _b, 1);
Gl.glColorMaterial(Gl.GL_FRONT_AND_BACK, Gl.GL_AMBIENT_AND_DIFFUSE);
Gl.glColorMaterial(Gl.GL_FRONT_AND_BACK, Gl.GL_SPECULAR);
for (int k = 0; k < square.Length; k++)
{ ////Begin loop for each side
scl = _scl;
float c = 0; //color counter rest
////////////// BEGIN SHAPE ////////////
Gl.glBegin(Gl.GL_QUAD_STRIP);
for (int i = 0; i < _length; i++)
{
if (i == 0)
{
acl = anchor - pos[i];
// acl.sub(anchor, pos[i]);
}
else
{
acl = pos[i - 1] - pos[i];
// acl.sub(pos[i - 1], (pos[i]));
}
float aclScale = .09f * (.1f * (i + 1));
acl.Scale(aclScale, aclScale, aclScale);

vel[i] += acl;
pos[i] += vel[i];
// vel[i].add(acl);
// pos[i].add(vel[i]);

////////// MAKE ARROW HEAD /////////////
if (_tip)
{
if (i == 0)
{
scl = 0;
}
else if (i == 1)
{
scl = _scl * 3f;
Vector3 arrowhead = new Vector3(vel[0]);
//arrowhead.set(vel[0]);
arrowhead.Normalize();
arrowhead.Scale(Size / 3f, Size / 3f, Size / 3f);
pos[1] -= arrowhead;
//pos[1].sub(arrowhead);
//pos[2].add(arrow);

}
else
{
scl = _scl;
}
if (i == 2)
{
pos[i]=pos[i - 1];
}
}
/////////////////////////////////////////

///////// SETUP AXIS VECTORS /////////////
vz=(acl);
vz.Normalize();

vx = Vector3.Cross(vz,up);
//vx.cross(vz, up);
vx.Normalize();
vy = Vector3.Cross(vz,vx);
//vy.cross(vz, vx);
vy.Normalize();
//////////////////////////////////////////

///////////// CREATE MATRIX //////////////
// Vector4 mvx = new Vector4(vx);

Matrix4 mat = new Matrix4(new Vector4(vx), new Vector4(vy), new Vector4(vz), new Vector4(pos[i]));

Matrix4 sclm = Matrix4.Scale(scl);

////////////// ALIGN SQUARE //////////////
Vector4[] temp = new Vector4[4];
Vector4[] sqscl = new Vector4[4];
for (int j = 0; j < square.Length; j++)
{

sqscl[j] = Vector3.Transform(square[j],sclm);
temp[j] = Vector4.Transform(sqscl[j], mat);

// sclm.transform(square[j], sqscl[j]);

// mat.transform(sqscl[j], temp[j]);
}
//////////////////////////////////////////

//////////// TOP /////////////
if (k == 0)
{
Gl.glNormal3f(-vy.X, -vy.Y, -vy.Z);
Gl.glVertex3f(temp[0].X, temp[0].Y, temp[0].Z);
Gl.glVertex3f(temp[1].X, temp[1].Y, temp[1].Z);
}
/////////// RIGHT ////////////
else if (k == 1)
{
Gl.glNormal3f(vx.X, vx.Y, vx.Z);
Gl.glVertex3f(temp[1].X, temp[1].Y, temp[1].Z);
Gl.glVertex3f(temp[2].X, temp[2].Y, temp[2].Z);
}
/////////// BOTTOM ///////////
else if (k == 2)
{
Gl.glNormal3f(vy.X, vy.Y, vy.Z);
Gl.glVertex3f(temp[2].X, temp[2].Y, temp[2].Z);
Gl.glVertex3f(temp[3].X, temp[3].Y, temp[3].Z);
}
/////////// LEFT /////////////
else if (k == 3)
{
Gl.glNormal3f(-vx.X, -vx.Y, -vx.Z);
Gl.glVertex3f(temp[3].X, temp[3].Y, temp[3].Z);
Gl.glVertex3f(temp[0].X, temp[0].Y, temp[0].Z);
}
float velscl = .8f - (.015f * i);
vel[i].Scale(velscl, velscl, velscl);
c += .018f;
// scl-=.0125; /// Scale decrement

}
Gl.glEnd();
//////////////// END SHAPE ///////////////////
}
}
}


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
sgsrules's picture

I was able to profile my application and the performance hogs where the vector.transform methods most likely since theres no method that can pass values by reference. Either way i switched all my code to use slimDX and the performance boost was pretty ridiculous. The original test using opentk.math ran a loop 20 times at about 25fps, when i switched to slimdx mat functions i was able to run the same test looped 200 times at 38 fps, thats a pretty big difference.

Inertia's picture

You do neither understand the difference between managed code vs. platform optimized code, nor the difference between measuring time in seconds vs. fps - do you?