Ios 是否允许指向Objective-C数组的指针(通过桥接头)?

Ios 是否允许指向Objective-C数组的指针(通过桥接头)?,ios,objective-c,swift,opengl-es,Ios,Objective C,Swift,Opengl Es,我一直在尝试从苹果公司获取样本,并在swift项目中运行。不幸的是,这在很大程度上依赖于使用C风格的线程安全阵列,该阵列仅在Objective-C中可用 我一直在尝试使用桥接标头,以便模拟可以在Objective-C代码中运行,绘图可以在swift代码中运行。这样线程安全就不会成为问题 我已经将Objective-C代码几乎完全翻译成swift,只有少数例外。我确实剔除了一些额外的数学,因为纹理与屏幕大小相同,以满足我的需要。如果你想查看我的翻译,我已经把它们放在下面了 无论如何,我已经创建了一

我一直在尝试从苹果公司获取样本,并在swift项目中运行。不幸的是,这在很大程度上依赖于使用C风格的线程安全阵列,该阵列仅在Objective-C中可用

我一直在尝试使用桥接标头,以便模拟可以在Objective-C代码中运行,绘图可以在swift代码中运行。这样线程安全就不会成为问题

我已经将Objective-C代码几乎完全翻译成swift,只有少数例外。我确实剔除了一些额外的数学,因为纹理与屏幕大小相同,以满足我的需要。如果你想查看我的翻译,我已经把它们放在下面了

无论如何,我已经创建了一个类,它将在任何带有opengl环境的xcode项目中运行

import Foundation
import GLKit
import OpenGLES

class WaterDrawer
{
    static var sim = RippleModel()
    static var shade = Shader("Shader2")

    static func pt(pt: CGPoint)
    {
        sim.initiateRippleAtLocation(pt)
    }
    static func firstStart(width: Int, height: Int)
    {
        sim.initWithScreenWidth(width / 4, iheight: height / 4, accWidth: width, accHeight: height)
        shade.begin()
        buildMatrix(width, height: height)
        bufferSetup()
    }

    static func draw()
    {
        glUseProgram(shade.progId)


        let posLoc = GLuint(glGetAttribLocation(shade.progId, "pos"))
        let texLoc = GLuint(glGetAttribLocation(shade.progId, "tc"))


        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);
        glBufferData(GLenum(GL_ARRAY_BUFFER), GLsizeiptr(sim.getVertexSize()), sim.getTexCoords(), GLenum(GL_DYNAMIC_DRAW));
        glVertexAttribPointer(texLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, BUFFER_OFFSET(0))
        glEnableVertexAttribArray(texLoc)

        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO)
        glVertexAttribPointer(posLoc, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, BUFFER_OFFSET(0))
        glEnableVertexAttribArray(posLoc)


        let uniOrtho = glGetUniformLocation(shade.progId, "matrix")
        glUniformMatrix4fv(uniOrtho, 1, GLboolean(GL_FALSE), &orthographicMatrix)


        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO)


        glDrawElements(GLenum(GL_TRIANGLE_STRIP), GLsizei(sim.getIndexCount()), GLenum(GL_UNSIGNED_SHORT), nil)

        glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)
        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)
        glDisableVertexAttribArray(posLoc)
        glDisableVertexAttribArray(texLoc)
    }

    static func update()
    {
        sim.runSimulation()
    }


    static var posVBO:GLuint = 0
    static var texVBO:GLuint = 0
    static var indVBO:GLuint = 0
    static func bufferSetup()
    {
        Whirl.crashLog("Started passing in buffer data")

        glGenBuffers(1, &indVBO);
        glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indVBO);
        glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), GLsizeiptr(sim.getIndexSize()), sim.getIndices(), GLenum(GL_STATIC_DRAW));

        glGenBuffers(1, &posVBO);
        glBindBuffer(GLenum(GL_ARRAY_BUFFER), posVBO);
        glBufferData(GLenum(GL_ARRAY_BUFFER), GLsizeiptr(sim.getVertexSize()), sim.getVertices(), GLenum(GL_STATIC_DRAW));


        glGenBuffers(1, &texVBO);
        glBindBuffer(GLenum(GL_ARRAY_BUFFER), texVBO);
        glBufferData(GLenum(GL_ARRAY_BUFFER), GLsizeiptr(sim.getVertexSize()), sim.getTexCoords(), GLenum(GL_DYNAMIC_DRAW));

        Whirl.crashLog("Finished passing in buffer Data")
    }


    static var orthographicMatrix:[GLfloat] = []
    static func buildMatrix(width: Int, height: Int)
    {
        orthographicMatrix = glkitmatrixtoarray(GLKMatrix4MakeOrtho(0, GLfloat(width), 0, GLfloat(height), -100, 100))
        //Storage.upScaleFactor
    }
    static func glkitmatrixtoarray(mat: GLKMatrix4) -> [GLfloat]
    {
        var buildme:[GLfloat] = []
        buildme.append(mat.m.0)
        buildme.append(mat.m.1)
        buildme.append(mat.m.2)
        buildme.append(mat.m.3)
        buildme.append(mat.m.4)
        buildme.append(mat.m.5)
        buildme.append(mat.m.6)
        buildme.append(mat.m.7)
        buildme.append(mat.m.8)
        buildme.append(mat.m.9)
        buildme.append(mat.m.10)
        buildme.append(mat.m.11)
        buildme.append(mat.m.12)
        buildme.append(mat.m.13)
        buildme.append(mat.m.14)
        buildme.append(mat.m.15)
        return buildme

    }

}
理论上,这段代码可以使用swift实现,也可以使用Objective-C实现,我只需要切换网格启动的方式

问题是当我使用Objective-C时,屏幕是空白的,我已经检查过了,缓冲区数据在帧捕获中看起来非常奇怪

是否允许将数据从Objective-C代码传递到glBuffer?

模拟。swift

import Foundation
import GLKit
import OpenGLES


class RippleModel
{
    var screenWidth:UInt32 = 0
    var screenHeight:UInt32 = 0
    var poolWidth:UInt32 = 0
    var poolHeight:UInt32 = 0
    var screenWidthi:Int = 0
    var screenHeighti:Int = 0
    var poolWidthi:Int = 0
    var poolHeighti:Int = 0

    let touchRadius:Int = 5 //5 i think

    var rippleVertices:[GLfloat] = []
    var rippleTexCoords:[GLfloat] = []
    var rippleIndices:[GLushort] = []//NOTE IF CHANGE THIS TO INTO SO MUCH DRAW CALL

    var rippleSource:[GLfloat] = []
    var rippleDest:[GLfloat] = []

    var rippleCoeff:[GLfloat] = []


    var VertexSize:GLsizeiptr = 0
    var IndicieSize:GLsizeiptr = 0
    var IndicieCount:Int = 0

    func calculateSizes()
    {
        VertexSize = rippleVertices.count * sizeof(GLfloat)
        IndicieSize = rippleIndices.count * sizeof(GLushort)
        IndicieCount = rippleIndices.count

        Whirl.crashLog("Data sizes Vertex size \(VertexSize)\tIndicie Size \(IndicieSize) \tIndicie Count \(IndicieCount)")
    }
    func figureOutCoefficent()
    {
        for y in 0...(2 * touchRadius)
        {
            for x in 0...(2 * touchRadius)
            {
                let dx = x - touchRadius
                let dy = y - touchRadius
                let distance = sqrt(GLfloat(dx * dx + dy * dy))

                let me = y * (touchRadius*2 + 1) + x
                if (distance <= GLfloat(touchRadius))
                {
                    let factor = distance / GLfloat(touchRadius)
                    rippleCoeff[me] = -(cos(factor*GLfloat(M_PI))+1.0) * 256.0;
                }
                else
                {
                    rippleCoeff[me] = 0.0
                }
            }
        }

    }
    init()
    {

    }
    func initWithScreenWidth( iwidth: Int,  iheight: Int, accWidth: Int, accHeight: Int)
    {
        screenWidth = UInt32(accWidth);screenWidthi = Int(screenWidth)
        screenHeight = UInt32(accHeight);screenHeighti = Int(screenHeight)

        poolWidth = UInt32(iwidth);poolWidthi = Int(poolWidth)
        poolHeight = UInt32(iheight);poolHeighti = Int(poolHeight)


        //WE DONT NEED TEX COORD MUMBO JUMBO IT IS FULL SCREEN ALREADY
        Whirl.crashLog("Started allocation")

        rippleCoeff = [GLfloat](count: Int( (touchRadius * 2 + 1) * (touchRadius*2 + 1) ), repeatedValue: 0)
        figureOutCoefficent()

        let simCount:Int = Int(poolWidth + 2) * Int(poolHeight + 2)
        rippleSource = [GLfloat](count: simCount, repeatedValue: 0)
        rippleDest = [GLfloat](count: simCount, repeatedValue: 0)

        let locb:Int = Int(poolWidth * poolHeight * 2)
        rippleVertices = [GLfloat](count: locb, repeatedValue: 0)
        rippleTexCoords = [GLfloat](count: locb, repeatedValue: 0)

        rippleIndices = [GLushort](count: Int(poolHeight - 1) * Int((poolWidth * 2) + 2), repeatedValue: 0)

        Whirl.crashLog("Finished allocation")

        initMesh()

        calculateSizes()
    }
    func initMesh()
    {
        Whirl.crashLog("Started initting pos coords")

        for i in 0..<poolHeight
        {let ii = GLfloat(i)
            for j in 0..<poolWidth
            {let jj = GLfloat(j)
                let cordb:Int = Int(i*poolWidth+j)*2


                rippleVertices[cordb + 0] = (jj / GLfloat(poolWidth - 1)) * GLfloat(screenWidth)
                rippleVertices[cordb + 1] = (ii / GLfloat(poolHeight - 1)) * GLfloat(screenHeight)


                rippleTexCoords[cordb + 0] = ii / GLfloat(poolHeight - 1)
                rippleTexCoords[cordb + 1] = (jj/GLfloat(poolWidth - 1))

            }
        }

        Whirl.crashLog("Finished initting pos coords")

        Whirl.crashLog("Started initting index coords")

        var index = 0
        for i in 0 ..< poolHeighti-1
        {
            for j in 0 ..< poolWidthi
            {
                if (i%2 == 0)
                {
                    // emit extra index to create degenerate triangle
                    if (j == 0)
                    {
                        rippleIndices[index] = GLushort(i*poolWidthi+j);
                        index += 1;
                    }

                    rippleIndices[index] = GLushort(i*poolWidthi+j);
                    index += 1;
                    rippleIndices[index] = GLushort((i+1)*poolWidthi+j);
                    index += 1;

                    // emit extra index to create degenerate triangle
                    if (j == (poolWidthi-1))
                    {
                        rippleIndices[index] = GLushort((i+1)*poolWidthi+j);
                        index += 1;
                    }
                }
                else
                {
                    // emit extra index to create degenerate triangle
                    if (j == 0)
                    {
                        rippleIndices[index] = GLushort((i+1)*poolWidthi+j);
                        index += 1;
                    }

                    rippleIndices[index] = GLushort((i+1)*poolWidthi+j);
                    index += 1;
                    rippleIndices[index] = GLushort(i * poolWidthi + j);
                    index += 1;

                    // emit extra index to create degenerate triangle
                    if (j == (poolWidthi-1))
                    {
                        rippleIndices[index] = GLushort(i * poolWidthi + j);
                        index += 1;
                    }
                }
            }
        }


        Whirl.crashLog("Finished initting coords")
    }

    var firstUpdate = true
    func runSimulation()
    {
        if (firstUpdate)
        {firstUpdate = false; Whirl.crashLog("First update")}

        let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

        //dispatch_apply(Int(poolHeight), queue, {(y: size_t) -> Void in
        for y in 0..<poolHeighti {
            let pw = self.poolWidthi
            for x in 1..<(pw - 1)
            {
                let ai:Int = (y    ) * (pw + 2) + x + 1
                let bi:Int = (y + 2) * (pw + 2) + x + 1
                let ci:Int = (y + 1) * (pw + 2) + x
                let di:Int = (y + 1) * (pw + 2) + x + 2
                let me:Int = (y + 1) * (pw + 2) + x + 1

                let a = self.rippleSource[ai]
                let b = self.rippleSource[bi]
                let c = self.rippleSource[ci]
                let d = self.rippleSource[di]

                var result = (a + b + c + d) / 2.0 - self.rippleDest[me]
                result -= result / 32.0

                self.rippleDest[me] = result
            }
        }
        //)


        let hm1 = GLfloat(poolHeight - 1)
        let wm1 = GLfloat(poolWidth - 1)
        //dispatch_apply(poolHeighti, queue, {(y: size_t) -> Void in
        for y in 0..<poolHeighti{
            let yy = GLfloat(y)
            let pw = self.poolWidthi
            for x in 1..<(pw - 1)
            {let xx = GLfloat(x)
                let ai:Int = (y    ) * (pw + 2) + x + 1
                let bi:Int = (y + 2) * (pw + 2) + x + 1
                let ci:Int = (y + 1) * (pw + 2) + x
                let di:Int = (y + 1) * (pw + 2) + x + 2

                let a = self.rippleDest[ai]
                let b = self.rippleDest[bi]
                let c = self.rippleDest[ci]
                let d = self.rippleDest[di]

                var s_offset = ((b - a) / 2048)
                var t_offset = ((c - d) / 2048)

                s_offset = (s_offset < -0.5) ? -0.5 : s_offset;
                t_offset = (t_offset < -0.5) ? -0.5 : t_offset;
                s_offset = (s_offset >  0.5) ?  0.5 : s_offset;
                t_offset = (t_offset >  0.5) ?  0.5 : t_offset;

                let s_tc = yy / hm1
                let t_tc = xx / wm1

                let me = (y * pw + x) * 2
                self.rippleTexCoords[me + 0] = s_tc + s_offset
                self.rippleTexCoords[me + 1] = t_tc + t_offset

            }
        }
        //)

        let pTmp = rippleDest
        rippleDest = rippleSource
        rippleSource = pTmp
    }

    var firstRipple:Bool = true
    func initiateRippleAtLocation(location: CGPoint)
    {
        if (firstRipple)
        {firstRipple = false; Whirl.crashLog("First ripple placement")}

        let xIndex = Int((GLfloat(location.x) / GLfloat(screenWidth)) * GLfloat(poolWidthi))
        let yIndex = Int((1.0 - (GLfloat(location.y) / GLfloat(screenHeighti))) * GLfloat(poolHeight))

        let lowy = yIndex - touchRadius
        let highy = yIndex + touchRadius
        let lowx = xIndex - touchRadius
        let highx = xIndex + touchRadius


        //Whirl.crashLog("Ripple at (\(xIndex) , \(yIndex))\tX:(\(lowx) - \(highx))\tY:(\(lowy) - \(highy))")

        for y in lowy...highy
        {
            for x in lowx...highx
            {
                if (x > 0 && x < (poolWidthi - 1) && y > 0 && y < poolHeighti)
                {
                    let ind = (poolWidthi + 2) * (y + 1) + x + 1
                    let coef = (y-(yIndex-touchRadius))*(touchRadius*2+1)+x-(xIndex-touchRadius)
                    let past = rippleSource[ind]
                    let coe = rippleCoeff[coef]
                    if (coe < past)
                    {
                        rippleSource[ind] = coe
                    }

                }
            }
        }
    }

    func rippleLine(location1: CGPoint, location2: CGPoint)
    {
        if (firstRipple)
        {firstRipple = false; Whirl.crashLog("First ripple placement")}

        let xIndex1 = Int((GLfloat(location1.x) / GLfloat(screenWidth)) * GLfloat(poolWidthi))
        let yIndex1 = Int((1.0 - (GLfloat(location1.y) / GLfloat(screenHeighti))) * GLfloat(poolHeight))
        let xIndex2 = Int((GLfloat(location2.x) / GLfloat(screenWidth)) * GLfloat(poolWidthi))
        let yIndex2 = Int((1.0 - (GLfloat(location2.y) / GLfloat(screenHeighti))) * GLfloat(poolHeight))

        let lowy1 = yIndex1 - touchRadius
        let highy1 = yIndex1 + touchRadius
        let lowx1 = xIndex1 - touchRadius
        let highx1 = xIndex1 + touchRadius

        let lowy2 = yIndex2 - touchRadius
        let highy2 = yIndex2 + touchRadius
        let lowx2 = xIndex2 - touchRadius
        let highx2 = xIndex2 + touchRadius

        let lowx = min(lowx1, lowx2)
        let highx = max(highx1, highx2)
        let lowy = min(lowy1, lowy2)
        let highy = max(highy1, highy2)

        for y in lowy...highy
        {
            for x in lowx...highx
            {
                if (x > 0 && x < (poolWidthi - 1) && y > 0 && y < poolHeighti)
                {
                    let ind = (poolWidthi + 2) * (y + 1) + x + 1

                    let tar = ldist(CGPoint(x: xIndex1, y: yIndex1), p2: CGPoint(x: xIndex2, y: yIndex2), me: CGPoint(x: x, y: y))

                    let dx = x - Int(tar.x)
                    let dy = y - Int(tar.y)
                    let distq = (dx * dx + dy * dy)

                    if (distq < touchRadius * touchRadius)
                    {
                        let factor = sqrt(GLfloat(distq)) / GLfloat(touchRadius)

                        rippleSource[ind] = -(cos(factor*GLfloat(M_PI))+1.0) * 256.0;
                    }
                    //rippleSource[ind] = 1000
                }
            }
        }
    }

    func ldist(p1: CGPoint, p2: CGPoint, me: CGPoint) -> CGPoint
    {
        let diffX = p2.x - p1.x
        let diffY = p2.y - p1.y

        var target = CGPoint()
        if ((diffX == 0) && (diffY == 0))
        {
            target = p1
        }

        let t = ((me.x - p1.x) * diffX + (me.y - p1.y) * diffY) / (diffX * diffX + diffY * diffY)

        if (t < 0)
        {
            target = p1
        }
        else if (t > 1)
        {
            target = p2
        }
        else
        {
            target = CGPoint(x: (p1.x + t * diffX), y: (p1.y + t * diffY))
        }

        let int = CGPoint(x: round(target.x), y: round(target.y))
        return int
    }

    func getVertices() -> [GLfloat]
    {
        //Return the mesh positions
        return rippleVertices
    }
    func getTexCoords() -> [GLfloat]
    {
        //Return the array of texture coords
        return rippleTexCoords
    }
    func getIndices() -> [GLushort]
    {
        //Return the array of indices
        return rippleIndices
    }
    func getVertexSize() -> GLsizeiptr
    {
        //Return the size of the mesh position array
        return VertexSize
    }
    func getIndexSize() -> GLsizeiptr
    {
        //Return the byte size of the incicie array
        return IndicieSize
    }
    func getIndexCount() -> GLsizeiptr
    {
        //This goes in the draw call, count of indices
        return IndicieCount
    }
}
<代码>导入基础 进口GLKit 导入OpenGLES 类RippleModel { 变量屏幕宽度:UInt32=0 变量屏幕高度:UInt32=0 变量池宽度:UInt32=0 变量池高度:UInt32=0 变量screenWidthi:Int=0 变量屏幕高度i:Int=0 变量PoolWidthSi:Int=0 var poolHeighti:Int=0 我想让touchRadius:Int=5//5 变量rippleVertices:[GLfloat]=[] var rippleTexCoords:[GLfloat]=[] var rippleIndices:[GLushort]=[]//注意如果将此更改为如此多的DRAW调用 var rippleSource:[GLfloat]=[] 变量RippleTest:[GLfloat]=[] 变量rippleCoeff:[GLfloat]=[] 变量VertexSize:GLsizeiptr=0 变量指示大小:GLsizeiptr=0 变量指示计数:Int=0 func calculateSizes() { VertexSize=rippleVertices.count*sizeof(GLfloat) IndicieSize=RippleIndicies.count*sizeof(GLushort) 指标计数=rippleIndices.count crashLog(“数据大小顶点大小\(顶点大小)\tIndicie大小\(指示大小)\tIndicie计数\(指示计数)”) } func计算效率() { 对于0中的y…(2*接触半径) { 对于0中的x…(2*touchRadius) { 设dx=x-接触半径 设dy=y-接触半径 让距离=sqrt(GLfloat(dx*dx+dy*dy)) 让我=y*(接触半径*2+1)+x 如果(距离0和x<(池宽i-1)和&y>0和&y<池高i) { 设ind=(i+2)*(y+1)+x+1 设tar=ldist(CGPoint(x:xIndex1,y:yIndex1),p2:CGPoint(x:xIndex2,y:yIndex2),me:CGPoint(x:x,y:y)) 设dx=x-Int(tar.x) 设dy=y-Int(tar.y) 设distq=(dx*dx+dy*dy) if(距离<接触半径*接触半径) { let factor=sqrt(GLfloat(distq))/GLfloat(touchRadius) rippleSource[ind]=-(cos(因子*GLfloat(M_PI))+1.0)*256.0; } //rippleSource[ind]=1000 } } } } func ldist(p1:CGPoint,p2:CGPoint,me:CGPoint)->CGPoint { 设diffX=p2.x-p1.x 设diffY=p2.y-p1.y var target=CGPoint() 如果((diffX==0)和&(diffY==0)) { 目标=p1 } 设t=((me.x-p1.x)*diffX+(me.y-p1.y)*diffY)/(diffX*diffX+diffY*diffY) if(t<0) { 目标=p1 } 否则如果(t>1) { 目标=p2 } 其他的 { 目标=CGPoint(x:(p1.x+t*diffX),y:(p1.y+t*diffY)) } 设int=CGPoint(x:round(target.x),y:round(target.y)) 返回整数 } func getVertices()->[GLfloat] { //返回网格位置 返回波纹 } func getTexCoords()->[GLfloat] { //返回纹理坐标数组 返回rippleTexCoords } func getindex()->[GLushort] { //返回索引数组 返回涟漪指数 } func getVertexSize()->GLsizeiptr { //返回网格位置数组的大小 返回顶点大小 } func getIndexSize()->GLsizeiptr { //返回incicie数组的字节大小 返回指示 } func getIndexCount()->GLsizeiptr { //这在draw调用中进行,索引计数 返回指示计数 } }

由于OpenGL ES是一组纯C函数,我认为传递swift数据类型的指针并不容易

下面的代码将提示您如何传递索引缓冲区

var Indices: [GLubyte] = [
    0, 1, 2,
    2, 3, 0
]

var indexBuffer: GLuint = GLuint()
glGenBuffers(1, &indexBuffer)
glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), Indices.size(), Indices, GLenum(GL_STATIC_DRAW))

参考:这里有一个工作代码链接

由于OpenGL ES是一组纯C函数,我认为传递swift数据类型的指针并不容易

下面的代码将提示您如何传递索引缓冲区

var Indices: [GLubyte] = [
    0, 1, 2,
    2, 3, 0
]

var indexBuffer: GLuint = GLuint()
glGenBuffers(1, &indexBuffer)
glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), Indices.size(), Indices, GLenum(GL_STATIC_DRAW))
参考:这里有一个工作代码链接

是否允许将数据从objective-c代码传递到glBuffer

你为什么不被允许?Swift有一个指针API(
UnsafePointer
UnsafeMutablePointer
等)正是为了这个目的。显然,这是“不安全的”,因为[Objective-]C指针指向的底层内存可能会在Swift指针不知道的情况下随时更改。它也没有关于它指向的内存块大小的信息

任何C指针或数组都可以桥接到Swift(可能是
unsafemeutablepointer)