SceneKit_中级04_约束的使用

2024-06-11 01:38
文章标签 使用 04 约束 中级 scenekit

本文主要是介绍SceneKit_中级04_约束的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

SceneKit_入门01_旋转人物
SceneKit_入门02_如何创建工程
SceneKit_入门03_节点
SceneKit_入门04_灯光
SceneKit_入门05_照相机
SceneKit_入门06_行为动画
SceneKit_入门07_几何体
SceneKit_入门08_材质
SceneKit_入门09_物理身体
SceneKit_入门10_物理世界
SceneKit_入门11_粒子系统
SceneKit_入门12_物理行为
SceneKit_入门13_骨骼动画
SceneKit_中级01_模型之间的过渡动画
SceneKit_中级02_SCNView 详细讲解
SceneKit_中级03_切换照相机视角
SceneKit_中级04_约束的使用
SceneKit_中级05_力的使用
SceneKit_中级06_场景的切换
SceneKit_中级07_动态修改属性
SceneKit_中级08_阴影详解
SceneKit_中级09_碰撞检测
SceneKit_中级10_滤镜效果制作
SceneKit_中级11_动画事件
SceneKit_高级01_GLSL
SceneKit_高级02_粒子系统深入研究
SceneKit_高级03_自定义力
SceneKit_高级04_自定义场景过渡效果
SceneKit_高级05 检测手势点击到节点
SceneKit_高级06_加载顶点、纹理、法线坐标
SceneKit_高级07_SCNProgram用法探究
SceneKit_高级08_天空盒子制作
SceneKit_高级09_雾效果
SceneKit_大神01_掉落的文字
SceneKit_大神02_弹幕来袭
SceneKit_大神03_navigationbar上的3D文字

1594482-ed6554e21af4cbc5.PNG
让学习成为一种习惯
先告诉你

我们在做应用开发的时候,也会用到约束,应用中的约束,就是当一个视图变化的时候,让和他之间有约束关系的其他视图,按照一定的约束规则变化,那在游戏中,我们的约束是用来干什么的?
官方的解释:

约束能够根据你定义的规则,自动调整这些变化(位置 旋转 和 比例)

认识新朋友
  • SCNConstraint

这个是游戏中的约束类,是一个抽象的类,我们不能直接使用,但是它有3个子类可以供我们使用。

我们看这个类有哪些属性

 /* * 作用: 影响因子,决定约束的强度* 工作原理: 如果设置为1 那么在游戏每一帧渲染的时候,系统都会调整这个约束,如果你设置为0.5 在游戏的某些帧,系统不会进行约束调整 0 完全忽略约束* 注意 SCNTransformConstraint  对这类约束不起作用*/var influenceFactor: CGFloat,默认值为 1,这是为0 时,则

接下来我们分析三个子类

  • SCNLookAtConstraint

1.作用:

让一个节点的方向,总是指向另外一个一个节点

2.怎么用? 我举个简单的例子,帮助大家理解它的用法

如果你想要玩第一视角的游戏,这是我们需要让摄像机捕捉到人物移动时的位置,这是需要给照相机节点添加一个SCNLookAtConstraint 类型的约束,就能实现这个效果。

3.原理:

其实这个约束的原理是更改节点的transform的属性

4.怎么创建

 // target 就是指向的那个目标节点 
+ (instancetype)lookAtConstraintWithTarget:(SCNNode *)target;

5.我们如果想要照相机的视野保持在水平面上,也就是说只沿在Y轴转动跟随目标节点,我们应该怎么做呢?

// 设置下面的属性为YES,就能实现上面的效果,默认为NO
var gimbalLockEnabled: Bool
  • SCNTransformConstraint

1.作用:

创建一个转换约束(提供给节点一个新的转换的计算),当系统进行下一次渲染的时候,会重新计算这个块中的约束,然后调整节点的状态

2.创建方法

 /** world 设置为YES 使用世界坐标系,设置为NO 使用自身坐标系 
+ (instancetype)transformConstraintInWorldSpace:(BOOL)world  withBlock:(SCNMatrix4 (^)(SCNNode *node,  SCNMatrix4 transform))block
  • SCNIKConstraint(反向运动约束)

1.作用:

将一个节点链移动到一个目标位置

给张图理解一下:

1594482-9d513f1985cd7ebf.png
让学习成为一种习惯

2.使用步骤:

1.创建一个节点链
2.给根节点添加 SCNIKConstraint 约束对象(胳膊)
3.添加约束給执行器(手)
3.限定链式节点移动的范围
4.设置目标位置,这个值可以动态的改变

3.举个例子理解一下

比如机器人的组成身体 上臂 胳膊 和 手,身体是上臂的根节点,上臂是胳膊的根节点,胳膊是手的根节点,手是身体的根节点,如果我们要实现上面的约束的话,需要将约束的根节点设置为上臂,那我们把这个约束应该添加到手(执行)这个节点上去

4.创建反向运动约束

- (instancetype)initWithChainRootNode:(SCNNode *)chainRoot  
+ inverseKinematicsConstraintWithChainRootNode:

5.设置约束的最大旋转角度

- (void)setMaxAllowedRotationAngle:(CGFloat)angleforJoint:(SCNNode *)node

6.设置目标位置

var targetPosition: SCNVector3
走进代码的世界

友情提示:

第一种约束和第二种约束都很简单,在这里就不写代码了,我们重点研究一下,第三种约束的实现。

1594482-576b02027764a980.png
制作一个机器手模型

1.创建工程(略)
2.添加模型文件(略)
3.添加框架<SceneKit/SceneKit.h>
4.创建游戏场景

scnView = [[SCNView alloc]initWithFrame:self.view.bounds];
scnView.backgroundColor = [UIColor blackColor];
scnView.allowsCameraControl = true;
scnView.scene = [SCNScene scene];
scnView.scene.physicsWorld.gravity = SCNVector3Make(0, 90, 0);// 添加一个重力,我们让其方向朝上
[self.view addSubview:scnView];

5.添加照相机

 SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.automaticallyAdjustsZRange = true;
cameraNode.position = SCNVector3Make(0, 0,1000);
[scnView.scene.rootNode addChildNode:cameraNode];

6.添加机器手臂并设置约束

-(void)addArmToScene{// 创建手掌
SCNNode *handNode = [SCNNode node];
handNode.geometry = [SCNBox boxWithWidth:20 height:20 length:20 chamferRadius:0];
handNode.geometry.firstMaterial.diffuse.contents = [UIColor purpleColor];
handNode.position = SCNVector3Make(0, -50, 0);// 创建小手臂
SCNNode *lowerArm = [SCNNode node];
lowerArm.geometry = [SCNCylinder cylinderWithRadius:1 height:100];
lowerArm.geometry.firstMaterial.diffuse.contents = [UIColor redColor];
lowerArm.position = SCNVector3Make(0, -50, 0);
lowerArm.pivot = SCNMatrix4MakeTranslation(0, 50, 0); // 连接点
[lowerArm addChildNode:handNode];// 创建上臂
SCNNode *upperArm = [SCNNode node];
upperArm.geometry = [SCNCylinder cylinderWithRadius:1 height:100];
upperArm.geometry.firstMaterial.diffuse.contents = [UIColor greenColor];
upperArm.pivot = SCNMatrix4MakeTranslation(0, 50, 0);
[upperArm addChildNode:lowerArm];// 创建控制点
SCNNode *controlNode = [SCNNode node];
controlNode.geometry = [SCNSphere sphereWithRadius:10];
controlNode.geometry.firstMaterial.diffuse.contents = [UIColor blueColor];
[controlNode addChildNode:upperArm];
controlNode.position= SCNVector3Make(0, 100, 0);// 添加到场景中去
[scnView.scene.rootNode addChildNode:controlNode];
scnView.delegate = self;// 创建约束ikContrait =[SCNIKConstraint inverseKinematicsConstraintWithChainRootNode:controlNode];// 给执行器添加约束
handNode.constraints = @[ikContrait];
}

7.添加一个手,每次点击屏幕,随机增加一个球

// 添加手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapHandle)];
[scnView addGestureRecognizer:tap];
-(void)tapHandle{
[self createNodeToScene:scnView.scene andConstraint:ikContrait];
}-(void)createNodeToScene:(SCNScene*)scene andConstraint:(SCNIKConstraint*)ikConstrait{
SCNNode *node = [SCNNode node];
node.position = SCNVector3Make(arc4random_uniform(100), arc4random_uniform(100), arc4random_uniform(100));
[scene.rootNode addChildNode:node];
node.geometry = [SCNSphere sphereWithRadius:10];
node.geometry.firstMaterial.diffuse.contents = [UIColor colorWithRed:arc4random_uniform(255.0)/255.0 green:arc4random_uniform(255.0)/255.0 blue:arc4random_uniform(255.0)/255.0 alpha:1];
// 创建动画,当手掌接触到小球时,给小球添加一个动态身体
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:0.5];
ikConstrait.targetPosition = node.position;
[SCNTransaction commit];
node.physicsBody = [SCNPhysicsBody dynamicBody];  
}

运行一下试试看:

1594482-05b0f998c8bdfdbb.gif
让学习成为一种习惯
总结

今天我们使用了反向运动约束,不知道你学会了没有,其他两种约束都比较简单,请自行进行学习,如有疑问,请联系我!


代码库,听说经常给人点赞都当老板了!

这篇关于SceneKit_中级04_约束的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1049857

相关文章

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意