我应该从结构和类切换到数组吗?

时间:2015-12-26 05:25:24

标签: arrays swift struct opengl-es

所以我有一个程序。而且我正在尝试模拟大量具有错综复杂的时刻逻辑的移动粒子,我不希望因为多种原因而进入CGP。当然,我将在GPU上绘制这一切。

现在最初我认为在模拟TONS粒子时,GPU延迟会成为问题,而不是CPU。不幸的是,我以高达6fps的速度运行500个粒子:(。

我已经跟踪了如何将顶点发送到粒子模拟器的延迟。甚至不是缓冲区创建,只是我如何构建数组。基本上我有数组我清除每一帧,然后遍历粒子数组中的每个粒子并为每个粒子创建数组。这导致大约17500个附加调用(具有500个粒子)。所以我需要一种不同的方法来实现这一点,因为如果不构建这些数组,它将以60fps运行,无cpu延迟。大多数这些追加调用都是一个结构的成员。

目前,每个粒子都是基于类对象制作的。并且它具有存储在结构中的位置和颜色等。将结构切换到数组会不会发生什么事?或许我应该将所有内容切换到数组?显然,做任何这些都会让事情变得更难。但它值得吗?

一个很大的问题是我需要将每个粒子绘制成一个胶囊。我用两个点和一条粗线做出来。不幸的是,OpenGL es 2.0不支持粗线,所以我必须用两个点和两个三角形绘制它们:(。你可以看到函数“calculateSquare”使得这两个三角形基于两点。它也非常迟钝但是,这不是唯一的问题,我会在以后尝试找到一种不同的方式。

你有什么想法?

注意:根据xcode ram的使用量仅为10 mb。但是cpu帧时间是141毫秒。

这是代码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
}

2 个答案:

答案 0 :(得分:0)

你真的需要系统RAM中的所有粒子吗?例如对于与场景中其他对象相关的一些物理碰撞计算?否则,您可以创建一个粒子,将其发送到GPU并在GPU着色器中进行计算。

答案 1 :(得分:0)

好的,经过几个小时的调整效率小代码的代码后,我得到它运行500粒子,fps为28,看起来非常流畅!我还有一些方法可以去。最好的建议与分配内存而不是附加内存有关。这节省了大量的问题。

特别感谢@Darko,@ Marcelo_Cantos提出了最终优化我的代码的想法!