C3DRendererContextSetupResidentMeshSourceAtLocation - SceneKit中不支持double

时间:2015-10-08 10:11:39

标签: objective-c

我正在尝试为iPhone重写此代码:

https://github.com/d-ronnqvist/DRMeshGeometry

代码在模拟器中工作,但iPhone会返回以下错误:

2015-10-08 12:04:37.564 3dtest[4253:1581829] SceneKit: error, C3DRendererContextSetupResidentMeshSourceAtLocation - double not supported
2015-10-08 12:04:37.566 3dtest[4253:1581829] SceneKit: error, C3DSourceAccessorToVertexFormat - invalid vertex format
/BuildRoot/Library/Caches/com.apple.xbs/Sources/Metal/Metal-54.31/Framework/MTLVertexDescriptor.mm:761: failed assertion `Unused buffer at index 18.'

错误在于此功能:

- (SCNGeometry *)geometryWithFunction:(DRMeshFunction)function
    {
    self.function = function;

    NSUInteger width = self.stepsPerAxisCounts.one;
    NSUInteger depth = self.stepsPerAxisCounts.two;

    NSUInteger pointCount = width * depth;

    SCNVector3  vertices[pointCount];
    SCNVector3  normals[pointCount];
    CGPoint     textures[pointCount];


    NSUInteger numberOfIndices = (2*width)*(depth);
    if (depth%4==0) numberOfIndices += 2;

    short indices[numberOfIndices];


    short lastIndex = 0;
    for (int row = 0 ; row<width-1 ; row++) {
        BOOL isEven = row%2 == 0;
        for (int col = 0 ; col<depth ; col++) {

            if (isEven) {
                indices[lastIndex] = row*width + col;
                lastIndex++;
                indices[lastIndex] = (row+1)*width + col;
                if (col == depth-1) {
                    lastIndex++;
                    indices[lastIndex] = (row+1)*width + col;
                }
            } else {
                indices[lastIndex] = row*width + (depth-1-col);
                lastIndex++;
                indices[lastIndex] = (row+1)*width + (depth-1-col);
                if (col == depth-1) {
                    lastIndex++;
                    indices[lastIndex] = (row+1)*width + (depth-1-col);
                }
            }
            lastIndex++;
        }
    }

    // Generate the mesh by calculating the vector, normal
    // and texture coordinate for each x,z pair.
    for (int row = 0 ; row<width ; row++) {
        for (int col = 0 ; col<depth ; col++) {

            CGFloat one = (float)col/(width-1) * (self.rangeOne.max - self.rangeOne.min) + self.rangeOne.min;
            CGFloat two = (float)row/(depth-1) * (self.rangeTwo.max - self.rangeTwo.min) + self.rangeTwo.min;

            SCNVector3 value = [self vectorForFunction:function one:one two:two];

            vertices[col + row*depth] = value;

            CGFloat delta = 0.001;
            SCNVector3 dx = vectorSubtract(value,
                                           [self vectorForFunction:function one:one+delta two:two]);

            SCNVector3 dz = vectorSubtract(value,
                                           [self vectorForFunction:function one:one two:two+delta]);

            normals[col + row*depth] = normalize( crossProduct(dz, dx) );


            textures[col + row*depth] = CGPointMake(col/(float)width*self.textureRepeatCounts.one,
                                                    row/(float)depth*self.textureRepeatCounts.two);
        }
    }

    // Create geometry sources for the generated data

    SCNGeometrySource *vertexSource  = [SCNGeometrySource geometrySourceWithVertices:vertices           count:pointCount];
    SCNGeometrySource *normalSource  = [SCNGeometrySource geometrySourceWithNormals:normals             count:pointCount];
    SCNGeometrySource *textureSource = [SCNGeometrySource geometrySourceWithTextureCoordinates:textures count:pointCount];


    // Configure the indices that was to be interpreted as a
    // triangle strip using

    SCNGeometryElement *element =
    [SCNGeometryElement geometryElementWithData:[NSData dataWithBytes:indices
                                                               length:sizeof(short[numberOfIndices])]
                                  primitiveType:SCNGeometryPrimitiveTypeTriangleStrip
                                 primitiveCount:numberOfIndices
                                  bytesPerIndex:sizeof(short)];

    // Create geometry from these sources
    SCNGeometry *geometry = [SCNGeometry geometryWithSources:@[vertexSource, normalSource, textureSource]
                                                elements:@[element]];

    // Since the builder exposes a geometry with repeating texture 
    // coordinates it is configured with a repeating material

    SCNMaterial *repeatingTextureMaterial = [SCNMaterial material];
    repeatingTextureMaterial.doubleSided = YES;

    // Possibly repeat all the materials texture coordintes here
    repeatingTextureMaterial.specular.contents = [UIColor colorWithWhite:0.3 alpha:1.0];
    repeatingTextureMaterial.shininess = .1250;

    geometry.materials = @[repeatingTextureMaterial];

    return geometry;
}

I really do not know what to try 

1 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,我找到了解决方法。

错误表示不支持double,实际上它是因CGPoint而使用double值的纹理坐标。

所以解决方案很简单,创建另一个结构来替换CGPoint,就像下面的代码一样。

更改

CGPoint textures[pointCount];
textures[col + row*depth] = CGPointMake(col/(float)width*self.textureRepeatCounts.one, row/(float)depth*self.textureRepeatCounts.two);

进入

typedef struct FloatPoint {
    float x;
    float y;
} FloatPoint;

FloatPoint textures[pointCount];

textures[col + row*depth] = (FloatPoint){col/(float)width*self.textureRepeatCounts.one, row/(float)depth*self.textureRepeatCounts.two};

更改

SCNGeometrySource *textureSource = [SCNGeometrySource geometrySourceWithTextureCoordinates:textures count:pointCount];

SCNGeometrySource *textureSource = [SCNGeometrySource geometrySourceWithData:[NSData dataWithBytes:textures length:sizeof(textures)]
                                                                    semantic:SCNGeometrySourceSemanticTexcoord
                                                                 vectorCount:pointCount
                                                             floatComponents:YES
                                                         componentsPerVector:2
                                                           bytesPerComponent:sizeof(float)
                                                                  dataOffset:offsetof(FloatPoint, x)
                                                                  dataStride:sizeof(FloatPoint)];