So I have a program. And I am trying to simulate tons of moving particles with intricate moment logic that i would not want to have going on the CGP for many reasons. Of course I am then going to draw this all on the GPU.
Now originally I thought that when simulating TONS of particles that GPU delay would be a problem not the CPU. Unfortunately I am running 500 particles at a whopping 6fps :(.
I have tracked the latency down to how I send the vertices to the particle simulator. And not even the buffer creation, simply how I build the arrays. Basically I have arrays I clear every frame, and then go through for each particle in an array of particles and create arrays for each of them. And this leads to around 17500 append calls (with 500 particles). So I need a different way to do this because without building these arrays it runs at 60fps no cpu latency. Most of these append calls call a member of a struct.
Currently each particle is made based off of a class object. And it has things like position and color that are stored in structs. Would it be wroth my while to switch structs to arrays? Or perhaps I should switch everything to arrays? Obviously doing any of that would make things much harder to program. But would it be worth it?
A big problem is that I need each particle to be drawn as a capsule. Which I would make out of two dots and a thick line. Unfortunately OpenGL es 2.0 doesn't support thick lines so I have to draw it with two dots and two triangles :(. As you can see the function "calculateSquare" makes these two triangles based off to the two points. It is also very laggy, however it isn't the only problem, I will try to find a different way later.
What are your thoughts?
Note: According to xcode ram usage is only at 10 mb. However the cpu frame time is 141 ms.
Here is the code BTW:
func buildParticleArrays()
{
lineStrip = []
lineStripColors = []
lineStripsize = []
s_vertes = []
s_color = []
s_size = []
for cparticle in particles
{
let pp = cparticle.lastPosition
let np = cparticle.position
if (cparticle.frozen == true)
{
addPoint(cparticle.position, color: cparticle.color, size: cparticle.size)
}
else
{
let s = cparticle.size / 2.0
//Add point merely adds the data in array format
addPoint(cparticle.position, color: cparticle.color, size: cparticle.size)
addPoint(cparticle.lastPosition, color: cparticle.color, size: cparticle.size)
lineStrip += calculateSquare(pp, pp2: np, size: s)
for var i = 0; i < 6; i++
{
let rgb = hsvtorgb(cparticle.color)
lineStripColors.append(GLfloat(rgb.r))
lineStripColors.append(GLfloat(rgb.g))
lineStripColors.append(GLfloat(rgb.b))
lineStripColors.append(GLfloat(rgb.a))
lineStripsize.append(GLfloat(cparticle.size))
}
}
}
}
func addPoint(theObject: point, color: colorhsv, size: CGFloat)
{
let rgb = hsvtorgb(color)
s_vertes += [GLfloat(theObject.x), GLfloat(theObject.y), GLfloat(theObject.z)]
s_color += [GLfloat(rgb.r), GLfloat(rgb.g), GLfloat(rgb.b), GLfloat(rgb.a)]
s_size.append(GLfloat(size))
}
func calculateSquare(pp1: point, pp2: point, size: CGFloat) -> [GLfloat]
{
let p1 = pp1
var p2 = pp2
var s1 = point()
var s2 = point()
let center = CGPointMake((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0)
var angle:CGFloat = 0
if ((p1.x == p2.x) && (p1.y == p2.y))
{
//They are ontop of eachother
angle = CGFloat(M_PI) / 2.0
p2.x += 0.0001
p2.y += 0.0001
}
else
{
if(p1.x == p2.x)
{
//UH OH x axis is equal
if (p1.y < p2.y)
{
//RESULT: p1 is lower so should be first
s1 = p1
s2 = p2
}
else
{
//RESULT: p2 is lower and should be first
s1 = p2
s2 = p1
}
}
else
{
//We could be all good
if (p1.y == p2.y)
{
//Uh oh y axis is equal
if (p1.x < p2.x)
{
//RESULT: p1 is left so should be first
s1 = p1
s2 = p2
}
else
{
//RESULT: p2 is to the right so should be first
s1 = p2
s2 = p1
}
}
else
{
//Feuf everything is ok
if ((p1.x < p2.x) && (p1.y < p2.y)) //First point is left and below
{
//P1 should be first
s1 = p1
s2 = p2
}
else //First point is right and top
{
//P2 should be first
s1 = p2
s2 = p1
}
}
}
angle = angle2p(s1, p2: s2)
}
if (angle < 0)
{
angle += CGFloat(M_PI) * 2.0
}
let yh = size / 2.0
let distance = dist(p1, p2: p2)
let xh = distance / 2.0
let tl = rotateVector(CGPointMake(-xh, yh), angle: angle) + center
let tr = rotateVector(CGPointMake(xh, yh), angle: angle) + center
let bl = rotateVector(CGPointMake(-xh, -yh), angle: angle) + center
let br = rotateVector(CGPointMake(xh, -yh), angle: angle) + center
let c1:[GLfloat] = [GLfloat(bl.x), GLfloat(bl.y), 0]
let c2:[GLfloat] = [GLfloat(tl.x), GLfloat(tl.y), 0]
let c3:[GLfloat] = [GLfloat(br.x), GLfloat(br.y), 0]
let c4:[GLfloat] = [GLfloat(tr.x), GLfloat(tr.y), 0]
let part1 = c1 + c2 + c3
let part2 = c2 + c3 + c4
return part1 + part2
}