1、SCNParametricGeometry简介
SCNParametricGeometry用于创建简单的3D模型,比如SCNPlane 平面、SCNPyramid 锥形(金字塔)、SCNBox 立方体、SCNSphere 球体、SCNCylinder 圆柱、SCNCone 圆锥体、SCNTube 圆柱管道、SCNCapsule 胶囊、SCNTorus 圆环面、SCNFloor 地板、SCNText 字体、SCNShape 自定义几何体!
2、SCNPlane 平面
- 效果图
- 相关代码
- (void)addPlane{ SCNPlane *plane = [SCNPlane planeWithWidth:10 height:3]; SCNNode *geoNode = [SCNNode nodeWithGeometry:plane]; plane.firstMaterial.multiply.contents = @"pic5.ipg"; plane.firstMaterial.diffuse.contents=@"pic5.ipg"; plane.firstMaterial.multiply.intensity = 0.5; plane.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:0 z:2 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
//初始化 + (instancetype)planeWithWidth:(CGFloat)width height:(CGFloat)height; //平面宽度 @property(nonatomic) CGFloat width; //平面高度 @property(nonatomic) CGFloat height; //沿X轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger widthSegmentCount; //沿Y轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount; //平面圆角半径 @property(nonatomic) CGFloat cornerRadius API_AVAILABLE(macos(10.9)); //圆角的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值是10。 @property(nonatomic) NSInteger cornerSegmentCount API_AVAILABLE(macos(10.9));
3、SCNBox 立方体
- 效果图
- 相关代码
- (void)addBody{ SCNBox *box = [SCNBox boxWithWidth:3 height:3 length:3 chamferRadius:0]; SCNNode *geoNode = [SCNNode nodeWithGeometry:box]; box.firstMaterial.multiply.contents = @"pic5.ipg"; box.firstMaterial.diffuse.contents=@"pic5.ipg"; box.firstMaterial.multiply.intensity = 0.5; box.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 2, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 创建立方体 @param width 宽度 @param height 高度 @param length 长度 @param chamferRadius 边的圆角半径 */ + (instancetype)boxWithWidth:(CGFloat)width height:(CGFloat)height length:(CGFloat)length chamferRadius:(CGFloat)chamferRadius; //宽度可动画 默认1 @property(nonatomic) CGFloat width; //高度可动画 默认1 @property(nonatomic) CGFloat height; //长度可动画 默认1 @property(nonatomic) CGFloat length; //圆角半径可动画 默认0 @property(nonatomic) CGFloat chamferRadius; //沿X轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger widthSegmentCount; //沿Y轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount; //沿Z轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger lengthSegmentCount; //圆角的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值是5。 @property(nonatomic) NSInteger chamferSegmentCount;
4、SCNPyramid 锥形(金字塔)
- 效果图
- 相关代码
- (void)addPyramid{ SCNPyramid *pyramid = [SCNPyramid pyramidWithWidth:5 height:10 length:5]; SCNNode *geoNode = [SCNNode nodeWithGeometry:pyramid]; pyramid.firstMaterial.multiply.contents = @"pic5.ipg"; pyramid.firstMaterial.diffuse.contents=@"pic5.ipg"; pyramid.firstMaterial.multiply.intensity = 0.5; pyramid.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 2, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param width 宽度 @param height 高度 @param length 长度 */ + (instancetype)pyramidWithWidth:(CGFloat)width height:(CGFloat)height length:(CGFloat)length; //宽度可动画 默认1 @property(nonatomic) CGFloat width; //高度可动画 默认1 @property(nonatomic) CGFloat height; //长度可动画 默认1 @property(nonatomic) CGFloat length; //沿Z轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1 @property(nonatomic) NSInteger widthSegmentCount; //沿Y轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1 @property(nonatomic) NSInteger heightSegmentCount; //沿Z轴的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1 @property(nonatomic) NSInteger lengthSegmentCount;
5、SCNSphere 球体
- 效果图
- 相关代码
- (void)addSphere{ SCNSphere *sphere = [SCNSphere sphereWithRadius:5]; SCNNode *geoNode = [SCNNode nodeWithGeometry:sphere]; sphere.firstMaterial.multiply.contents = @"pic5.ipg"; sphere.firstMaterial.diffuse.contents=@"pic5.ipg"; sphere.firstMaterial.multiply.intensity = 0.5; sphere.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
//初始化 球半径 + (instancetype)sphereWithRadius:(CGFloat)radius; //半径 @property(nonatomic) CGFloat radius; //是否用多边形网格来渲染球体 默认NO @property(nonatomic, getter=isGeodesic) BOOL geodesic; //沿经纬线的子划分数。可以做成动画。 //如果值小于3,则行为未定义。默认值为24 @property(nonatomic) NSInteger segmentCount;
6、SCNCylinder 圆柱
- 效果图
- 相关代码
- (void)addCylinder{ SCNCylinder *cylinder = [SCNCylinder cylinderWithRadius:6 height:10]; SCNNode *geoNode = [SCNNode nodeWithGeometry:cylinder]; cylinder.firstMaterial.multiply.contents = @"pic5.ipg"; cylinder.firstMaterial.diffuse.contents=@"pic5.ipg"; cylinder.firstMaterial.multiply.intensity = 0.5; cylinder.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param radius 圆柱半径 @param height 高度 */ + (instancetype)cylinderWithRadius:(CGFloat)radius height:(CGFloat)height; //半径 @property(nonatomic) CGFloat radius; //高度 @property(nonatomic) CGFloat height; //沿径向坐标的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是48。 @property(nonatomic) NSInteger radialSegmentCount; //在Y轴上的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount;
7、SCNCone 圆锥体
- 效果图
- 相关代码
- (void)addCone{ SCNCone *cone = [SCNCone coneWithTopRadius:2 bottomRadius:5 height:10]; SCNNode *geoNode = [SCNNode nodeWithGeometry:cone]; cone.firstMaterial.multiply.contents = @"pic5.ipg"; cone.firstMaterial.diffuse.contents=@"pic5.ipg"; cone.firstMaterial.multiply.intensity = 0.5; cone.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param topRadius 顶部半径(顶部为0时就是圆锥) @param bottomRadius 底部半径 @param height 高度 */ + (instancetype)coneWithTopRadius:(CGFloat)topRadius bottomRadius:(CGFloat)bottomRadius height:(CGFloat)height; //顶部半径可动画 默认0 @property(nonatomic) CGFloat topRadius; //底部半径可动画 默认0.5 @property(nonatomic) CGFloat bottomRadius; //高度可动画 默认1 @property(nonatomic) CGFloat height; //沿径向坐标的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是48。 @property(nonatomic) NSInteger radialSegmentCount; //在Y轴上的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount;
8、SCNTube 圆柱管道
- 效果图
- 相关代码
- (void)addTube{ SCNTube *tube = [SCNTube tubeWithInnerRadius:4 outerRadius:5 height:5]; SCNNode *geoNode = [SCNNode nodeWithGeometry:tube]; tube.firstMaterial.multiply.contents = @"pic5.ipg"; tube.firstMaterial.diffuse.contents=@"pic5.ipg"; tube.firstMaterial.multiply.intensity = 0.5; tube.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:2 y:0 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param innerRadius 内圆半径 @param outerRadius 外圆半径 @param height 高度 */ + (instancetype)tubeWithInnerRadius:(CGFloat)innerRadius outerRadius:(CGFloat)outerRadius height:(CGFloat)height; //内圆半径可动画 默认0.25 @property(nonatomic) CGFloat innerRadius; //外圆半径可动画 默认0.5 @property(nonatomic) CGFloat outerRadius; //高度可动画 默认1 @property(nonatomic) CGFloat height; //沿径向坐标的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是48。 @property(nonatomic) NSInteger radialSegmentCount; //在Y轴上的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount;
9、SCNCapsule 胶囊
- 效果图
- 相关代码
- (void)addCapsule{ SCNCapsule *capsule = [SCNCapsule capsuleWithCapRadius:2 height:10]; SCNNode *geoNode = [SCNNode nodeWithGeometry:capsule]; capsule.firstMaterial.multiply.contents = @"pic5.ipg"; capsule.firstMaterial.diffuse.contents=@"pic5.ipg"; capsule.firstMaterial.multiply.intensity = 0.5; capsule.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 6, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param capRadius 球半径 @param height 高度 */ + (instancetype)capsuleWithCapRadius:(CGFloat)capRadius height:(CGFloat)height; //两端球半径 可动画默认0.5 @property(nonatomic) CGFloat capRadius; //高度 可动画默认2 @property(nonatomic) CGFloat height; //沿径向坐标的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是48。 @property(nonatomic) NSInteger radialSegmentCount; //在Y轴上的子划分数。可以做成动画。 //如果值小于1,则行为未定义。默认值为1。 @property(nonatomic) NSInteger heightSegmentCount; //帽子上的子划分数。可以做成动画。 //如果值小于2,则行为未定义。默认值是24。 @property(nonatomic) NSInteger capSegmentCount;
10、SCNTorus 圆环面
- 效果图
- 相关代码
- (void)addToruse{ SCNTorus *torus = [SCNTorus torusWithRingRadius:4 pipeRadius:1]; SCNNode *geoNode = [SCNNode nodeWithGeometry:torus]; torus.firstMaterial.multiply.contents = @"pic5.ipg"; torus.firstMaterial.diffuse.contents=@"pic5.ipg"; torus.firstMaterial.multiply.intensity = 0.5; torus.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(0, 2, -20); [self.scnScene.rootNode addChildNode:geoNode]; [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 初始化 @param ringRadius 圆环外半径 @param pipeRadius 圆环半径 */ + (instancetype)torusWithRingRadius:(CGFloat)ringRadius pipeRadius:(CGFloat)pipeRadius; //圆环外半径 可动画默认0.5 @property(nonatomic) CGFloat ringRadius; //圆环半径 可动画默认0.25 @property(nonatomic) CGFloat pipeRadius; //环的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是48。 @property(nonatomic) NSInteger ringSegmentCount; //管子的子划分数。可以做成动画。 //如果值小于3,则该行为是未定义的。默认值是24。 @property(nonatomic) NSInteger pipeSegmentCount;
11、SCNFloor 地板
- 效果图(下面红色就是地板)
- 相关代码
- (void)addFloor{ SCNNode *node = [SCNNode node]; node.geometry = ({ SCNFloor *floor = [SCNFloor floor]; floor.firstMaterial.diffuse.contents = [UIImage imageNamed:@"sun.jpg"]; floor; }); node.position = SCNVector3Make(0, 0, 0); [self.scnScene.rootNode addChildNode:node]; }
- 相关属性
//初始化 + (instancetype)floor; //指定地板的反射率。可以做成动画。 //如果值大于零,则表面将反映场景中的其他对象。默认值为0.25。 @property(nonatomic) CGFloat reflectivity; //指定从地板开始下降的距离。可以做成动画。默认值为0。 @property(nonatomic) CGFloat reflectionFalloffStart; //指定从地板上的跌落结束的距离。可以做成动画。 //如果值为0,则没有衰减。默认值为0。 @property(nonatomic) CGFloat reflectionFalloffEnd; //确定要反射的节点类别 @property(nonatomic) NSUInteger reflectionCategoryBitMask API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0)); //在X轴上的地板范围。可以做成动画。 //如果值等于0,那么在X轴上的地板是无限的。默认值为0。 @property(nonatomic) CGFloat width API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0)); //在Z轴上的地板范围。可以做成动画。 //如果值为0,那么在Z轴上的地板是无限的。默认值为0。 @property(nonatomic) CGFloat length API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0)); //指定用于呈现反射的缓冲区的分辨率比例因子。默认0.5 @property(nonatomic) CGFloat reflectionResolutionScaleFactor API_AVAILABLE(macos(10.10));
12、SCNText 字体
- 效果图
- 相关代码
- (void)addText{ SCNText *text = [SCNText textWithString:@"你好" extrusionDepth:3]; text.font = [UIFont systemFontOfSize:8]; text.alignmentMode = kCAAlignmentCenter; SCNNode *geoNode = [SCNNode nodeWithGeometry:text]; text.firstMaterial.multiply.contents = @"pic5.ipg"; text.firstMaterial.diffuse.contents=@"pic5.ipg"; text.firstMaterial.multiply.intensity = 0.5; text.firstMaterial.lightingModelName = SCNLightingModelConstant; geoNode.position = SCNVector3Make(-8, 0, -20); [self.scnScene.rootNode addChildNode:geoNode]; [self addFloor]; [self addLight]; }
- 相关属性(官方图片)
/** 创建3D文字 @param string 文本 @param extrusionDepth 挤压深度 */ + (instancetype)textWithString:(nullable id)string extrusionDepth:(CGFloat)extrusionDepth; //挤压深度 可动画如果值为0就是单面2D版本 @property(nonatomic) CGFloat extrusionDepth; //文本必须是NSString或NSAttributedString的实例。 @property(nonatomic, copy, nullable) id string; //字体属性大小 默认值是Helvetica size 36。 @property(nonatomic, retain, null_resettable) UIFont *font; //文本是否被包装,要包装的文本,首先需要设置它的边界,否则文本不会被包装。默认值是NO。 @property(nonatomic, getter=isWrapped) BOOL wrapped; //设置文本包装 @property(nonatomic) CGRect containerFrame; //截断文本以适应边界 枚举默认值kCATruncationNone,具体参考CATextLayer.h @property(nonatomic, copy) NSString *truncationMode; //设置文本对齐方式 @property(nonatomic, copy) NSString *alignmentMode; CA_EXTERN NSString * const kCAAlignmentNatural CA_AVAILABLE_STARTING (10.5, 3.2, 9.0, 2.0); CA_EXTERN NSString * const kCAAlignmentLeft CA_AVAILABLE_STARTING (10.5, 3.2, 9.0, 2.0); CA_EXTERN NSString * const kCAAlignmentRight CA_AVAILABLE_STARTING (10.5, 3.2, 9.0, 2.0); CA_EXTERN NSString * const kCAAlignmentCenter CA_AVAILABLE_STARTING (10.5, 3.2, 9.0, 2.0); CA_EXTERN NSString * const kCAAlignmentJustified CA_AVAILABLE_STARTING (10.5, 3.2, 9.0, 2.0); //每个倒棱边的宽度或深度。可以做成动画。可以做成动画。 //值范围[0,挤压深度/ 2]。实际的倒角半径可能与此处指定的倒角不同:大的值被剪切到每个字符的最大值。默认值为0。 @property(nonatomic) CGFloat chamferRadius; //确定每个倒棱边的横截面轮廓的路径。 @property(nonatomic, copy, nullable) UIBezierPath *chamferProfile; //指定显示字体平滑度 //更小的数字会使曲线更平滑,而在顶点上的计算和更重的几何图形的代价更大。默认值是1.0,它会产生平滑的曲线。 @property(nonatomic) CGFloat flatness API_AVAILABLE(macos(10.9));
13、SCNShape 自定义几何体
- 效果图
- 相关代码
- (void)addPath{ UIBezierPath *path=[UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0, 0)]; [path addLineToPoint:CGPointMake(5, 5)]; [path addLineToPoint:CGPointMake(5, 6)]; [path addArcWithCenter:CGPointMake(2.5, 6) radius:2.5 startAngle:0 endAngle:M_PI clockwise:YES]; [path addArcWithCenter:CGPointMake(-2.5, 6) radius:2.5 startAngle:0 endAngle:M_PI clockwise:YES]; [path addLineToPoint:CGPointMake(-5, 5)]; [path closePath]; //添加路径 SCNShape *Cylinder = [SCNShape shapeWithPath:path extrusionDepth:6]; Cylinder.chamferMode =SCNChamferModeBoth; Cylinder.firstMaterial.diffuse.contents =[UIImage imageNamed:@"pic5.ipg"]; SCNNode *geoNode = [SCNNode nodeWithGeometry:Cylinder]; geoNode.position = SCNVector3Make(0, 0, -20); [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self.scnScene.rootNode addChildNode:geoNode]; [self addFloor]; [self addLight]; }
- 相关属性
//创建并返回给定形状与给定的挤压深度的3D模型 + (instancetype)shapeWithPath:(nullable UIBezierPath *)path extrusionDepth:(CGFloat)extrusionDepth; //定义要呈现的形状的路径。 @property(nonatomic, copy, nullable) UIBezierPath *path; //挤压深度。可以做成动画。 //如果值为0,我们得到一个单面的2D版本的形状。 @property(nonatomic) CGFloat extrusionDepth; //文本的侧边被倒角。默认值是SCNChamferModeBoth。 @property(nonatomic) SCNChamferMode chamferMode; typedef NS_ENUM(NSInteger, SCNChamferMode) { SCNChamferModeBoth, SCNChamferModeFront, SCNChamferModeBack } API_AVAILABLE(macos(10.9)); //倒角半径。可以做成动画。值被夹紧到范围[0,挤压深度/ 2]。默认值为0。 @property(nonatomic) CGFloat chamferRadius; //描述在“chamferRadius”不是nil时使用的概要文件。当“chamferProfile”为nil时,我们将返回表示象限的路径。 //概要文件应该是一个2D曲线,从(0,1)开始,到(1,0)结束。“平整度”属性也用来使这条路径变平。默认值为nil。 @property(nonatomic, copy, nullable) UIBezierPath *chamferProfile;
14、其它相关代码
- 灯光
- (void)addLight{ SCNLight *light = [SCNLight light]; light.type = SCNLightTypeOmni; light.color = [UIColor whiteColor]; self.scnNode.light = light; }
- 场景
- (SCNScene *)scnScene{ if (!_scnScene) { _scnScene = [SCNScene scene]; _scnScene.background.contents = @"Assets.xcassets/pic5.png"; _scnScene.physicsWorld.gravity = SCNVector3Make(0, -30, 0); } return _scnScene; }
- 根节点
- (SCNNode *)scnNode{ if (!_scnNode) { _scnNode = [[SCNNode alloc] init]; _scnNode.camera = [[SCNCamera alloc] init]; _scnNode.camera.zFar = 200.f; _scnNode.camera.zNear = .1f; // _scnNode.camera.projectionDirection = SCNCameraProjectionDirectionHorizontal; _scnNode.position = SCNVector3Make(0, 5, 20); } return _scnNode; }
- 视图view
- (SCNView *)scnView{ if (!_scnView) { _scnView = [[SCNView alloc] initWithFrame:self.view.bounds options:@{SCNViewOptionPreferLowPowerDevice:@"MTLDevice"}]; _scnView.showsStatistics = YES; _scnView.autoenablesDefaultLighting = YES; [self.view addSubview:_scnView]; _scnView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[_scnView]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scnView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_scnView]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_scnView)]]; } return _scnView; }
- 例子
- (void)viewDidLoad { [super viewDidLoad]; self.scnView.scene = self.scnScene; [self.scnScene.rootNode addChildNode:self.scnNode]; [self addPath]; } - (void)addPath{ UIBezierPath *path=[UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(0, 0)]; [path addLineToPoint:CGPointMake(5, 5)]; [path addLineToPoint:CGPointMake(5, 6)]; [path addArcWithCenter:CGPointMake(2.5, 6) radius:2.5 startAngle:0 endAngle:M_PI clockwise:YES]; [path addArcWithCenter:CGPointMake(-2.5, 6) radius:2.5 startAngle:0 endAngle:M_PI clockwise:YES]; [path addLineToPoint:CGPointMake(-5, 5)]; [path closePath]; //添加路径 SCNShape *Cylinder = [SCNShape shapeWithPath:path extrusionDepth:6]; Cylinder.chamferMode =SCNChamferModeBoth; Cylinder.firstMaterial.diffuse.contents =[UIImage imageNamed:@"pic5.ipg"]; SCNNode *geoNode = [SCNNode nodeWithGeometry:Cylinder]; geoNode.position = SCNVector3Make(0, 0, -20); [geoNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]]; [self.scnScene.rootNode addChildNode:geoNode]; [self addFloor]; [self addLight]; }