csg体素构造表示形式(Constructive Solid Geometry)

2023-10-30 14:20

本文主要是介绍csg体素构造表示形式(Constructive Solid Geometry),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

csg的全称是Constructive Solid Geometry,也就是体素构造表示形式。godot引擎中有支持。主要用于一些形状间的结合,通过联合,相交,相减的操作来组成一个新的网格体。这种技术在有号距离场的形状距离识别中也有相应的应用。Prototyping levels with CSG — Godot Engine (stable) documentation in English

核心方法是mergeBrushes

intersectsInclusive

intersectsInclusive首先会看a面和b面是否aabb相交,如果相交则会进入具体的相交计算,也就进入updateFaces中。

重点1:updateFaces

updateFaces这里会去掉一些顶点很接近的,而且updateFaces主要看相交情况,首先通过isPointOver和hasPoint看是否相交,其中isPointOver是判断(n.dot(point) > d);也就是如果这个数量为3则说明B面的三个顶点都在A面的另一面,这样是不会有相交的。

然后通过sat的轴分离方式查看是否相交。

SAT:

sat是基于轴分离来判断是否两个凸多边形相交,这里的做法是拿两个三角形的所有边叉乘,叉乘出的结果再跟刚刚拿出的两个三角形的边做点乘找出投影位置,然后两个投影距离相减,拿到投影的最大偏移和最小偏移,如果最大偏移还小于0或者最小偏移还大于0则说明两个三角形是不相交的。

 

具体原理在这里有写,向量运算实现碰撞系统_llsansun的博客-CSDN博客

如果相交则添加新的面,

 

insertFace:

这里主要看insertFace,

 

这里首先看是否A面包含B面的点,如果包含直接加入点,如果不包含,如果两个点都在面的同一边则不加,如果不在并且他们有相交距离则加入点。

findEdgeIntersections和addVertexIdxSorted

然后通过findEdgeIntersections来找是否是边缘相交,如果是边缘相交则要做特殊处理,不然会有缺陷,比如边缘被删除了那么整个mesh的形状就和原来的形状不一致了,如果有边缘则要添加面来补足。检查边是否存在,通过检查相交段是否与边平行。如果对点在线段上,将其索引也添加到线段索引中。  在新边缘周围创建两个新面,并删除该面。  

mergeFaces:

然后就执行mergeFaces,这里他会把相近的顶点去掉,不然他加入到面中,扁平的多个顶点的面也会去掉,以及如果是边缘,在新边缘周围创建两个新面,并删除该面。  

addFace:

然后通过addFacesToMesh和addFace的方式,让点和uv加入到meshMerge中,记录顶点的合并信息。然后加入到faces中,这个faces是用于后面的面的法线方向步进后看是否有相交的其他面用的,具体在markInsideFaces中。

重点2:markInsideFaces

然后执行markInsideFaces,这里是关键的合并记录中,通过createBvh创建层级数据结构二叉树,然后遍历所有的faces,intersectsInclusive看是否a的面和b面是否有相交

bvhInside

有相交才进入到具体的bvhInside判断,bvhInside这里的判断是遍历所有面,然后通过当前bvh中的面然后执行intersectsRay,遍历A面的当前中心位置以及法线方面查看是否有相交的属于另一个来源面的三角形(也就是fromA的面和fromB的面比较,如果都是fromA或者都是fromB则不比较),但是intersectsRay只是针对AABB的判断。

然后后面通过isPointInTriangle来检查两个面是否共面。

rayIntersectsTriangle

然后如果有相交再执行rayIntersectsTriangle具体的三角形的中心点和法线方向的另一个来源的三角形是否有相交。如果有则说明是再里面的三角形,记录inside为true。

最后他判断如果面内的法线与其他面相交奇数次则认为碰撞。

重点3:inside

然后在CSGBrushOperation::mergeBrushes的时候检测利用inside来组合三角形。

OPERATION_UNION

如果是OPERATION_UNION则如果inside是true的话就不结合到顶点和uv中。

OPERATION_INTERSECTION

如果是OPERATION_INTERSECTION则inside是false的话就不结合顶点和uv,也就是没有相交的部分不加入三角形中,只有相交才加入。

OPERATION_SUBTRACTION

如果是OPERATION_SUBTRACTION则如果面来自于b面的结合并且不是inside的,则不结合顶点和uv,如果不是来自于b面的但是相交也不结合。意思就是如果a和b面是不是在同一个面上的而且相交的则要记录顶点。

最终返回mergedBrush这个CSGBrush。

这篇关于csg体素构造表示形式(Constructive Solid Geometry)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

C++中类的构造函数调用顺序

当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的 构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。 简而言之,对象是由“底层向上”开始构造的。因为,构造函数一开始构造时,总是 要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时, 如果无专门说明,就调用直接基类的默认构造函数。在对象析构时,其顺序正好相反。

从计组中从重温C中浮点数表示及C程序翻译过程

目录 移码​编辑  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 例子:   ​编辑 浮点数取的过程   C程序翻译过程 移码  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 根据国际标准IEEE(电⽓和电⼦⼯程协会)  32位 例子:    64位    IEEE754对有效数字M和

Java构造和解析Json数据的两种方法(json-lib构造和解析Json数据, org.json构造和解析Json数据)

在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别。下面首先介绍用json-lib构造和解析Json数据的方法示例。 一、介绍       JSON-lib包是一个beans,collections,maps,java arrays 和XML和JSON互相转换的包,主要就是用来解析Json

通过Ajax请求后台数据,返回JSONArray(JsonObject),页面(Jquery)以table的形式展示

点击“会商人员情况表”,弹出层,显示一个表格,如下图: 利用Ajax和Jquery和JSONArray和JsonObject来实现: 代码如下: 在hspersons.html中: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>会商人员情况表</title><script type="text/javasc

CF #278 (Div. 2) B.(暴力枚举+推导公式+数学构造)

B. Candy Boxes time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/488/problem/B There

MemSQL Start[c]UP 2.0 - Round 1A(构造)

题目链接:http://codeforces.com/problemset/problem/452/A 解题思路: 打个表暴力查找匹配。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <complex>#include <cstdio>#include <strin

Codeforces Round #281 (Div. 2)A(构造+暴力模拟)

题目链接:http://codeforces.com/problemset/problem/493/A 解题思路: 暴力的判断,分三种情况去判断即可。注意如果之前已经被罚下场后,那么在后面的罚下情况不应该算在输出结果内。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <co

Codeforces Round #233 (Div. 2)A(构造)

题目链接:http://codeforces.com/contest/399/problem/A 解题思路: 构造出来即可,考虑p-k和p+k两个边界分别于1和n作比较,对左右符号特殊处理。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <complex>#include

Codeforces Round #247 (Div. 2)A(构造)

题目链接:http://codeforces.com/contest/431/problem/A 解题思路: 构造出来即可。 完整代码: #include <algorithm>#include <iostream>#include <cstring>#include <complex>#include <cstdio>#include <string>#inc