iOS显示STL文件(3D效果)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS显示STL文件(3D效果)相关的知识,希望对你有一定的参考价值。

参考技术A 由于项目需要,因此需要在项目中集成STL文件3D显示效果,最早解决方案是STL文件转DAE文件,使用SceneKit直接加载并显示出来,但是多了个步骤总是感觉很麻烦,后来想到使用OpenGL用来显示STL文件,而OpenGL那晦涩难懂的语法实在是浪费太多时间,所以写了个简单的项目(基于ScentKit)用来集成STL的文件显示。
首先对于STL文件的内容请参考 STL文件解析 ,STL文件分为两种编码格式,一种为ASCII,一种为二进制,具体区别请自行查看。
这里以SceneKit为例,首先创建一个类继承自SCNView:

实现方法:
首先实现初始化方法:

使用传递的路径初始化场景:
这里场景的光照原来一直是自己打的,后来发现自己打的光怎么样都不好看,所以使用了默认的光源。

在这里加载STL文件(顺便区分STL文件的编码方式)

加载二进制的STL文件:

加载ASCII编码的STL文件:

好了,那么既然解析方法和显示方法都已经创建完毕,那么接下来显示STL文件就简单很多了:

最终效果如图所示:

在 macOS 的 SceneKit 中无法显示 stl 文件

【中文标题】在 macOS 的 SceneKit 中无法显示 stl 文件【英文标题】:Trouble displaying stl file in SceneKit with macOS 【发布时间】:2019-12-14 18:48:43 【问题描述】:

我有一个二进制 stl 文件,它可以在 ios scenekit 中显示,但不能在具有相同代码的 macOS 中显示。当我加载文件时,有时应用程序崩溃,有时它显示错误的东西

macOS 10.14.6


- (SCNNode *)loadBinarySTLWithData:(NSData *)data

NSMutableData *vertices = [NSMutableData data];
NSMutableData *normals = [NSMutableData data];
NSMutableData *elements = [NSMutableData data];
if (data.length % 50 != 0)
    return nil;

NSInteger allCount = data.length/50;
for (int i = 0; i < allCount; i ++)
    for (int j = 1; j <= 3; j ++)
        [normals appendData:[data subdataWithRange:NSMakeRange(i * 50, 12)]];
        [vertices appendData:[data subdataWithRange:NSMakeRange(i * 50 + j*12, 12)]];
    
    int element[3] = (int)i * 3,(int)i*3 + 1,(int)i*3 + 2;
    [elements appendBytes:&element[0] length:sizeof(element)];

SCNGeometrySource *verticesSource = [SCNGeometrySource geometrySourceWithData:vertices semantic:SCNGeometrySourceSemanticVertex vectorCount:allCount*3 floatComponents:YES componentsPerVector:3 bytesPerComponent:sizeof(float) dataOffset:0 dataStride:sizeof(SCNVector3)];
SCNGeometrySource *normalsSource = [SCNGeometrySource geometrySourceWithData:normals semantic:SCNGeometrySourceSemanticNormal vectorCount:allCount*3 floatComponents:YES componentsPerVector:3 bytesPerComponent:sizeof(float) dataOffset:0 dataStride:sizeof(SCNVector3)];
SCNGeometryElement *geoMetryElement = [SCNGeometryElement geometryElementWithData:elements primitiveType:SCNGeometryPrimitiveTypeTriangles primitiveCount:allCount bytesPerIndex:sizeof(int)];
SCNGeometry *geometry = [SCNGeometry geometryWithSources:@[verticesSource,normalsSource] elements:@[geoMetryElement]];
geometry.firstMaterial.diffuse.contents = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
geometry.firstMaterial.doubleSided = YES;
SCNNode *node = [SCNNode nodeWithGeometry:geometry];
return node;

【问题讨论】:

【参考方案1】:

SCNVector3 在 iOS 和 macOS 上有不同的声明:

// iOS
typedef struct SCNVector3 
    float x, y, z;
 SCNVector3;
// macOS
typedef struct SCNVector3 
    CGFloat x, y, z;
 SCNVector3;

当为 64 位编译时,CGFloatdouble。 这意味着sizeof(SCNVector3) 不是 macOS 上的正确步幅。你应该改用3 * sizeof(float)

【讨论】:

以上是关于iOS显示STL文件(3D效果)的主要内容,如果未能解决你的问题,请参考以下文章

unity3d 模型怎么双面显示

## 利用MPU6050 + OLED屏显示cube3D矩形效果

在 SceneKit/modelIO 中测量 3D-Obj 文件上两点之间的距离并显示它们

在 macOS 的 SceneKit 中无法显示 stl 文件

3D Slicer中文教程—导出STL文件

如何3d模型在web网页显示展示?用啥技术