├── book.jpg
├── taichi.png
├── Lab2 N-body
├── show.png
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
├── PythonApplication.sln
└── PythonApplication
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── Lab4 Dominoes
├── show.png
├── PythonApplication
│ ├── imgui.ini
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
└── PythonApplication.sln
├── Lab1 Crash-balls
├── show.png
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── PythonApplication.sln
├── README.md
└── PythonApplication
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── Lab7 Path-tracing
├── show.png
├── PythonApplication
│ ├── imgui.ini
│ ├── __pycache__
│ │ └── head.cpython-311.pyc
│ ├── PythonApplication.pyproj
│ ├── PythonApplication.py
│ └── head.py
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
└── PythonApplication.sln
├── Lab8 Stable-fluid
├── show.png
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── PythonApplication
│ ├── __pycache__
│ │ └── head.cpython-311.pyc
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── README.md
└── PythonApplication.sln
├── Lab3 Cloth-simulation
├── fuck.jpeg
├── show.png
├── PythonApplication
│ ├── imgui.ini
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
└── PythonApplication.sln
├── Lab5 Water-simulation
├── fuck.jpg
├── show.png
├── PythonApplication
│ ├── imgui.ini
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── Position Based Fluids.pdf
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
└── PythonApplication.sln
├── Lab6 Temperature-diffuse
├── show.png
├── PythonApplication
│ ├── imgui.ini
│ ├── PythonApplication.pyproj
│ └── PythonApplication.py
├── .vs
│ └── PythonApplication
│ │ └── v16
│ │ └── .suo
├── README.md
└── PythonApplication.sln
├── README_zh.md
└── README.md
/book.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/book.jpg
--------------------------------------------------------------------------------
/taichi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/taichi.png
--------------------------------------------------------------------------------
/Lab2 N-body/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab2 N-body/show.png
--------------------------------------------------------------------------------
/Lab4 Dominoes/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab4 Dominoes/show.png
--------------------------------------------------------------------------------
/Lab1 Crash-balls/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab1 Crash-balls/show.png
--------------------------------------------------------------------------------
/Lab7 Path-tracing/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab7 Path-tracing/show.png
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab8 Stable-fluid/show.png
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/fuck.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab3 Cloth-simulation/fuck.jpeg
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab3 Cloth-simulation/show.png
--------------------------------------------------------------------------------
/Lab4 Dominoes/PythonApplication/imgui.ini:
--------------------------------------------------------------------------------
1 | [Window][Debug##Default]
2 | Pos=60,60
3 | Size=400,400
4 | Collapsed=0
5 |
6 |
--------------------------------------------------------------------------------
/Lab5 Water-simulation/fuck.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab5 Water-simulation/fuck.jpg
--------------------------------------------------------------------------------
/Lab5 Water-simulation/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab5 Water-simulation/show.png
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab6 Temperature-diffuse/show.png
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication/imgui.ini:
--------------------------------------------------------------------------------
1 | [Window][Debug##Default]
2 | Pos=60,60
3 | Size=400,400
4 | Collapsed=0
5 |
6 |
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/PythonApplication/imgui.ini:
--------------------------------------------------------------------------------
1 | [Window][Debug##Default]
2 | Pos=60,60
3 | Size=400,400
4 | Collapsed=0
5 |
6 |
--------------------------------------------------------------------------------
/Lab5 Water-simulation/PythonApplication/imgui.ini:
--------------------------------------------------------------------------------
1 | [Window][Debug##Default]
2 | Pos=60,60
3 | Size=400,400
4 | Collapsed=0
5 |
6 |
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/PythonApplication/imgui.ini:
--------------------------------------------------------------------------------
1 | [Window][Debug##Default]
2 | Pos=60,60
3 | Size=400,400
4 | Collapsed=0
5 |
6 |
--------------------------------------------------------------------------------
/Lab2 N-body/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab2 N-body/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab4 Dominoes/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab4 Dominoes/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab1 Crash-balls/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab1 Crash-balls/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab5 Water-simulation/Position Based Fluids.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab5 Water-simulation/Position Based Fluids.pdf
--------------------------------------------------------------------------------
/Lab7 Path-tracing/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab7 Path-tracing/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab8 Stable-fluid/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab3 Cloth-simulation/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab5 Water-simulation/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab5 Water-simulation/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/.vs/PythonApplication/v16/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab6 Temperature-diffuse/.vs/PythonApplication/v16/.suo
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication/__pycache__/head.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab7 Path-tracing/PythonApplication/__pycache__/head.cpython-311.pyc
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/PythonApplication/__pycache__/head.cpython-311.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ayinzhang/Taichi-Projects/HEAD/Lab8 Stable-fluid/PythonApplication/__pycache__/head.cpython-311.pyc
--------------------------------------------------------------------------------
/Lab7 Path-tracing/README.md:
--------------------------------------------------------------------------------
1 | # Lab7 Path-tracing
2 |
3 | **康奈尔盒子简易路径追踪**
4 |
5 | **~~没想到吧,我又来做渲染了~~**
6 |
7 |
8 |

9 |
10 |
11 |
--------------------------------------------------------------------------------
/Lab4 Dominoes/README.md:
--------------------------------------------------------------------------------
1 | # Lab4 Dominoes
2 |
3 | **多刚体碰撞模拟,各式向量运算和罗德里格旋转公式**
4 |
5 | **~~field为什么不能整体自定义赋值?field间嵌套为什么会报错?还有你这UGUI操作怎么这么像OpenGL?~~**
6 |
7 |
8 |

9 |
10 |
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/README.md:
--------------------------------------------------------------------------------
1 | # Lab8 Stable-fluid
2 |
3 | **欧拉视角半拉格朗日平流加雅可比投影**
4 |
5 | **~~模拟,渲染,游戏开发......时至今日,依旧迷茫~~**
6 |
7 | *p 暂停模拟*
8 |
9 | *r 重置模拟*
10 |
11 | *Esc 退出模拟*
12 |
13 |
14 |

15 |
16 |
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/README.md:
--------------------------------------------------------------------------------
1 | # Lab6 Temperature-diffuse
2 |
3 | **隐式线性求解温度传播,稀疏矩阵和线性求解器的初探**
4 |
5 | **~~逃跑未遂,第二弹开始营业。Taichi,启动!~~**
6 |
7 | *Space 暂停模拟*
8 |
9 | *r 重置模拟*
10 |
11 | *Esc 退出模拟*
12 |
13 |
14 |

15 |
16 |
--------------------------------------------------------------------------------
/Lab2 N-body/README.md:
--------------------------------------------------------------------------------
1 | # N-body
2 |
3 | **空间数据结构加速的多体天体模型,初始随机体积位置并环绕**
4 |
5 | **~~从O(n^2) 干到O(nlogn),O(n)的自适应快速多级方法不可能的,洗洗睡吧梦里什么都有~~**
6 |
7 |
8 |
9 | *鼠标左键 对所有天体施加引力*
10 |
11 | *鼠标右键 对所有天体施加斥力*
12 |
13 | *Esc 退出程序*
14 |
15 |
16 |
17 |
18 |

19 |
20 |
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/README.md:
--------------------------------------------------------------------------------
1 | # Cloth-simulation
2 |
3 | **布料模拟,运用了基于胡克定律的PBD改进**
4 |
5 | **~~被Taichi的自动并行化和混乱的数据结构整的硬de了一天的bug~~**
6 |
7 |
8 |

9 |
Taichi你个狗杂种!
10 |
11 |
12 |

13 |
14 |
--------------------------------------------------------------------------------
/Lab5 Water-simulation/README.md:
--------------------------------------------------------------------------------
1 | # Lab5 Water-simulation
2 |
3 | **PBF流体模拟,Position Based Fluids的复现**
4 |
5 | **~~说的几十万个粒子实时呢?我这开一万个还没模拟就炸了,GTX1650也不算太低吧这~~**
6 |
7 |
8 |

9 |
Taichi再见了您嘞!
10 |
11 |
12 |

13 |
14 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | # Taichi项目
2 |
3 | [English Version](README.md)
4 |
5 | **假期及实习间隙做的一些杂项,部分基于Taichi图形课以及《基于物理的建模与动画》**
6 |
7 | *Lab1 GUI碰撞模拟 回溯碰撞解除,五种积分方式*
8 |
9 | *Lab2 GUI多体天体模拟 空间数据结构加速,初始随机体积位置并环绕*
10 |
11 | *Lab3 GGUI布料模拟,基于胡克定律的PBD改进*
12 |
13 | *Lab4 GGUI多刚体碰撞模拟,各式向量运算和罗德里格旋转公式*
14 |
15 | *Lab5 GUI三维PBF流体模拟,Position Based Fluids的复现*
16 |
17 | *Lab6 GUI隐式线性求解温度传播,稀疏矩阵和线性求解器的初探*
18 |
19 | *Lab7 GUI路径追踪,康奈尔盒子简易路径追踪*
20 |
21 | *Lab8 GUI流体扩散,欧拉视角半拉格朗日平流加雅可比投影*
22 |
23 |
24 |

25 |
26 |
27 |
28 |

29 |
30 |
--------------------------------------------------------------------------------
/Lab2 N-body/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab4 Dominoes/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab1 Crash-balls/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab5 Water-simulation/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/PythonApplication.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31829.152
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "PythonApplication", "PythonApplication\PythonApplication.pyproj", "{73E3B394-3719-4284-B58C-3CBFFD15CC5B}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {73E3B394-3719-4284-B58C-3CBFFD15CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | GlobalSection(ExtensibilityGlobals) = postSolution
21 | SolutionGuid = {F5A7264E-DEB0-4076-BB00-7375D8AE76A3}
22 | EndGlobalSection
23 | EndGlobal
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Taichi-projects
2 |
3 | [中文版](README_zh.md)
4 |
5 | **Miscellaneous works done during holidays and internship breaks, some based on Taichi graphics class and 'Physics based Modeling and Animation'**
6 |
7 | *Lab1 GUI collision simulation backtracking collision release, five integration methods*
8 |
9 | *Lab2 GUI multi-body celestial body simulation space data structure acceleration, initial random volume position and surrounding*
10 |
11 | *Lab3 GGUI Fabric Simulation, PBD Improvement Based on Hooke's Law*
12 |
13 | *Lab4 GGUI Multi Body Collision Simulation, Various Vector Operations, and Rodrigues Rotation Formula*
14 |
15 | *Lab5 GUI 3D PBF fluid simulation, reproduction of Position Based Fluids*
16 |
17 | *Lab6 GUI Preliminary Exploration of implicit Linear Solution for Temperature Propagation, Sparse Matrix, and Linear Solver*
18 |
19 | *Lab7 GUI Path Tracking, Cornell Box Easy Path Tracking*
20 |
21 | *Lab8 GUI fluid diffusion, Euler perspective semi Lagrangian advection with Jacobian projection*
22 |
23 |
24 |

25 |
26 |
27 |
28 |

29 |
30 |
--------------------------------------------------------------------------------
/Lab1 Crash-balls/README.md:
--------------------------------------------------------------------------------
1 | # Crash-balls
2 |
3 | **回溯碰撞解除的碰撞球模型,可选择五种积分方式(显式欧拉,隐式欧拉,半隐式欧拉,速度韦尔莱,二阶龙格库塔)**
4 |
5 | **~~但作者本人表示看不出啥区别~~**
6 |
7 |
8 |
9 | *鼠标左键 添加碰撞球*
10 |
11 | *w/s 增加/减少重力分量*
12 |
13 | *d/a 增加/减少风力分量*
14 |
15 | *↑/↓ 增加/减少潮湿度数*
16 |
17 | *→/← 增加/减少风力分量*
18 |
19 | *q 切换欧拉算法*
20 |
21 | *r 清除所有碰撞球*
22 |
23 | *Esc 退出程序*
24 |
25 |
26 |
27 | *Explicit Euler's Method:*
28 | $$
29 | \vec v(t_1)=\vec v(t_0)+M^{-1}\vec F(t_0)\Delta t
30 | $$
31 | $$
32 | x(t_1)=x(t_0)+\vec v(t_0)\Delta t
33 | $$
34 | *Implicit Euler's Method:*
35 | $$
36 | \vec v(t_1)=\vec v(t_0)+M^{-1}\vec F(t_1)\Delta t
37 | $$
38 | $$
39 | x(t_1)=x(t_0)+\vec v(t_1)\Delta t
40 | $$
41 | *Semi_Implicit Euler's Method:*
42 | $$
43 | \vec v(t_1)=\vec v(t_0)+M^{-1}\vec F(t_0)\Delta t
44 | $$
45 | $$
46 | x(t_1)=x(t_0)+\vec v(t_1)\Delta t
47 | $$
48 |
49 | *Velocity Welley*
50 | $$
51 | x(t_1)=x(t_0)+\vec v(t_0)\Delta t+\frac{1}{2}M^{-1}\vec F(t_0)\Delta t^2
52 | $$
53 |
54 | $$
55 | \vec v(t_1)=\vec v(t_0)+\frac{1}{2}M^{-1}(\vec F(t_0)+\vec F(t_1))\Delta t
56 | $$
57 |
58 | *Runge Kutta2*
59 | $$
60 | \vec v(t_1)=\vec v(t_0)+M^{-1}\vec F(t_0)\Delta t
61 | $$
62 |
63 | $$
64 | x(t_{0.5})=x(t_0)+\frac{1}{2}\vec v(t_0)\Delta t
65 | $$
66 |
67 | $$
68 | \vec v(t_{0.5})=\vec v(t_0)+\frac{1}{2}M^{-1}\vec F(t_{0.5})\Delta t
69 | $$
70 |
71 | $$
72 | x(t_1) = x(t_0)+\vec v(t_{0.5})\Delta t
73 | $$
74 |
75 |
76 |
77 |
78 |

79 |
80 |
--------------------------------------------------------------------------------
/Lab2 N-body/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab4 Dominoes/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab1 Crash-balls/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab5 Water-simulation/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication/PythonApplication.pyproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 | 73e3b394-3719-4284-b58c-3cbffd15cc5b
6 | .
7 | PythonApplication.py
8 |
9 |
10 | .
11 | .
12 | PythonApplication
13 | PythonApplication
14 |
15 |
16 | true
17 | false
18 |
19 |
20 | true
21 | false
22 |
23 |
24 |
25 | Code
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Lab6 Temperature-diffuse/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import taichi as ti
2 | ti.init(ti.cpu)
3 |
4 | k = 3000
5 | n = 512
6 | dt = 1e-2
7 | radius = 64
8 | t_min = 0
9 | t_max = 300
10 | paused = False
11 | n2 = n * n
12 | c = dt * k
13 | t = ti.field(ti.f32, n2)
14 | pixels = ti.Vector.field(3, ti.f32, (n, n))
15 | D_Builder = ti.linalg.SparseMatrixBuilder(n2, n2, 5 * n2)
16 |
17 | @ti.kernel
18 | def fillDiffusionMatrixBuilder(A: ti.types.sparse_matrix_builder()):
19 | for i,j in ti.ndrange(n, n):
20 | num = 0.0
21 | if i - 1 >= 0:
22 | A[i * n + j, (i - 1) * n + j] -= c
23 | num += c
24 | if i + 1 < n:
25 | A[i * n + j, (i + 1) * n + j] -= c
26 | num += c
27 | if j - 1 >= 0:
28 | A[i * n + j, i * n + j - 1] -= c
29 | num += c
30 | if j + 1 < n:
31 | A[i * n + j, i * n + j + 1] -= c
32 | num += c
33 | A[i * n + j, i * n + j] += num + 1
34 |
35 | @ti.kernel
36 | def init():
37 | for i,j in ti.ndrange(n, n):
38 | if (i - n // 2) ** 2 + (j - n // 2) ** 2 <= radius ** 2:
39 | t[i * n + j] = t_max
40 | else:
41 | t[i * n + j] = t_min
42 |
43 | @ti.kernel
44 | def update_sourse():
45 | for i in range(n // 2 - radius, n // 2 + radius + 1):
46 | for j in range(n // 2 - radius, n // 2 + radius + 1):
47 | if (i - n // 2) ** 2 + (j - n // 2) ** 2 <= radius ** 2:
48 | t[i * n + j] = t_max
49 |
50 | @ti.kernel
51 | def cook(t: ti.template(), color: ti.template(), t_min: ti.f32, t_max: ti.f32):
52 | for i,j in ti.ndrange(n, n):
53 | color[i, j] = ti.Vector([1, 1, 1])
54 | d = t_max - t_min
55 | if t[i * n + j] < (t_min + 0.25 * d):
56 | color[i, j][0] = 0
57 | color[i, j][1] = 4 * (t[i * n + j] - t_min) / d
58 | elif t[i * n + j] < (t_min + 0.5 * d):
59 | color[i, j][0] = 0
60 | color[i, j][2] = 1 + 4 * (t_min + 0.25 * d - t[i * n + j]) / d
61 | elif t[i * n + j] < (t_min + 0.75 * d):
62 | color[i, j][0] = 4 * (t[i * n + j] - t_min - 0.5 * d) / d
63 | color[i, j][2] = 0
64 | else:
65 | color[i, j][1] = 1 + 4 * (t_min + 0.75 * d - t[i * n + j]) / d
66 | color[i, j][2] = 0
67 |
68 | gui = ti.GUI("Temperature-diffuse", (n, n))
69 | init()
70 | fillDiffusionMatrixBuilder(D_Builder)
71 | D = D_Builder.build()
72 | solver = ti.linalg.SparseSolver(solver_type="LLT")
73 | solver.analyze_pattern(D)
74 | solver.factorize(D)
75 | ti.profiler.clear_kernel_profiler_info()
76 | while gui.running:
77 | for e in gui.get_events(ti.GUI.PRESS):
78 | if e.key == ti.GUI.SPACE:
79 | paused = not paused
80 | elif e.key == ti.GUI.ESCAPE:
81 | gui.running = False
82 | elif e.key == 'r':
83 | init()
84 | if not paused:
85 | t.from_numpy(solver.solve(t))
86 | update_sourse()
87 | cook(t, pixels, t_min, t_max)
88 | gui.set_image(pixels)
89 | gui.show()
--------------------------------------------------------------------------------
/Lab2 N-body/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import taichi as ti
2 | ti.init(ti.gpu)
3 |
4 | n = 300
5 | G = 6.67e-11
6 | block_size = 12
7 | galaxy_size = 0.45
8 | planet_radius = 2
9 | dt = 1e-5
10 | substepping = 10
11 |
12 | r = ti.field(ti.f32, n)
13 | m = ti.field(ti.f32, n)
14 | p = ti.Vector.field(2, ti.f32, n)
15 | v = ti.Vector.field(2, ti.f32, n)
16 | f = ti.Vector.field(2, ti.f32, n)
17 | b = ti.field(ti.i32)
18 | block = ti.root.dense(ti.ij, [block_size, block_size])
19 | index = block.dynamic(ti.k, n)
20 | index.place(b)
21 |
22 | @ti.kernel
23 | def init():
24 | center = ti.Vector([0.5, 0.5])
25 | for i in range(n):
26 | theta = ti.random() * 2 * ti.math.pi
27 | d = (ti.sqrt(ti.random()) * 0.7 + 0.3) * galaxy_size
28 | offset = d * ti.Vector([ti.cos(theta), ti.sin(theta)])
29 | r[i] = (ti.random() + 0.5) * planet_radius
30 | m[i] = r[i] ** 3;
31 | p[i] = center + offset
32 | b[ti.math.floor(p[i].x * block_size, ti.i32), ti.math.floor(p[i].y * block_size, ti.i32)].append(i)
33 | v[i] = [-offset.y, offset.x]
34 | v[i] *= 120 * (ti.sqrt(ti.random()) + 0.5)
35 |
36 | @ti.kernel
37 | def compute():
38 | for i in range(n):
39 | f[i] = ti.Vector([0.0, 0.0])
40 | for i in range(n):
41 | x = ti.math.clamp(ti.math.floor(p[i].x * block_size, ti.i32), 0, block_size - 1)
42 | y = ti.math.clamp(ti.math.floor(p[i].y * block_size, ti.i32), 0, block_size - 1)
43 | for j in range(-1, 2):
44 | for k in range(-1, 2):
45 | if 0 <= x + j and x + j < block_size and 0 <= y + k and y + k < block_size:
46 | for l in range(b[x + j, y + k].length()):
47 | o = b[x + j, y + k, l]
48 | if i != o:
49 | r = ti.math.length(p[i] - p[o])
50 | force = G * m[i] * m[o] / (r ** 3) * (p[o] - p[i])
51 | f[i] += force
52 | f[o] -= force
53 |
54 | @ti.kernel
55 | def pull(xpos:ti.f32, ypos:ti.f32):
56 | pos = [xpos, ypos]
57 | for i in range(n):
58 | f[i] += (pos - p[i]) ** 3 * 12000000
59 |
60 | @ti.kernel
61 | def push(xpos:ti.f32, ypos:ti.f32):
62 | pos = [xpos, ypos]
63 | for i in range(n):
64 | f[i] += (p[i] - pos) ** 3 * 12000000
65 |
66 | @ti.kernel
67 | def update():
68 | for i in range(block_size):
69 | for j in range(block_size):
70 | b[i, j].deactivate()
71 | for i in range(n):
72 | v[i] += dt * f[i] / m[i]
73 | p[i] += dt * v[i]
74 | x = ti.math.clamp(ti.math.floor(p[i].x * block_size, ti.i32), 0, block_size - 1)
75 | y = ti.math.clamp(ti.math.floor(p[i].y * block_size, ti.i32), 0, block_size - 1)
76 | b[x, y].append(i)
77 |
78 |
79 | gui = ti.GUI("n-body", (512, 512))
80 | init()
81 | while gui.running:
82 | compute()
83 | for e in gui.get_events(ti.GUI.PRESS):
84 | if e.key == ti.GUI.LMB:
85 | pull(e.pos[0], e.pos[1])
86 | if e.key == ti.GUI.RMB:
87 | push(e.pos[0], e.pos[1])
88 | if e.key == ti.GUI.ESCAPE:
89 | gui.running = False
90 | update()
91 | gui.clear(0x112F41)
92 | gui.circles(p.to_numpy(), color=0xffffff, radius=r.to_numpy())
93 | gui.show()
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | from head import *
2 | ti.init(ti.gpu)
3 |
4 | width = 600
5 | height = 600
6 | samples = 16
7 | depth = 16
8 |
9 | @ti.kernel
10 | def render():
11 | for i, j in canvas:
12 | u = (i + ti.random()) / width
13 | v = (j + ti.random()) / height
14 | color = ti.Vector([0.0, 0.0, 0.0])
15 | for k in range(samples):
16 | ray = camera.get_ray(u, v)
17 | color += get_color(ray)
18 | color /= samples
19 | canvas[i, j] += color
20 |
21 | @ti.func
22 | def get_color(ray):
23 | color_buffer = ti.Vector([0.0, 0.0, 0.0])
24 | brightness = ti.Vector([1.0, 1.0, 1.0])
25 | scattered_origin = ray.origin
26 | scattered_direction = ray.direction
27 | rate = 0.85
28 | for n in range(depth):
29 | if ti.random() > rate:
30 | break
31 | is_hit, hit_point, hit_point_normal, front_face, material, color = scene.hit(Ray(scattered_origin, scattered_direction))
32 | if is_hit:
33 | if material == 0:
34 | color_buffer = color * brightness
35 | break
36 | else:
37 | if material == 1:
38 | target = hit_point + hit_point_normal
39 | target += random_unit_vector()
40 | scattered_direction = target - hit_point
41 | scattered_origin = hit_point
42 | brightness *= color
43 | elif material == 2 or material == 4:
44 | fuzz = 0.0
45 | if material == 4:
46 | fuzz = 0.5
47 | scattered_direction = reflect(scattered_direction.normalized(), hit_point_normal)
48 | scattered_direction += fuzz * random_unit_vector()
49 | scattered_origin = hit_point
50 | if scattered_direction.dot(hit_point_normal) < 0:
51 | break
52 | else:
53 | brightness *= color
54 | elif material == 3:
55 | refraction_ratio = 1.5
56 | if front_face:
57 | refraction_ratio = 1 / refraction_ratio
58 | cos_theta = min(-scattered_direction.normalized().dot(hit_point_normal), 1.0)
59 | sin_theta = ti.sqrt(1 - cos_theta * cos_theta)
60 | if refraction_ratio * sin_theta > 1.0 or reflectance(cos_theta, refraction_ratio) > ti.random():
61 | scattered_direction = reflect(scattered_direction.normalized(), hit_point_normal)
62 | else:
63 | scattered_direction = refract(scattered_direction.normalized(), hit_point_normal, refraction_ratio)
64 | scattered_origin = hit_point
65 | brightness *= color
66 | brightness /= rate
67 | return color_buffer
68 |
69 | camera = Camera()
70 | scene = Hittable_list()
71 | canvas = ti.Vector.field(3, dtype=ti.f32, shape=(width, height))
72 | scene.add(Sphere(center=ti.Vector([0, 5.4, -1]), radius=3.0, material=0, color=ti.Vector([10.0, 10.0, 10.0])))
73 | scene.add(Sphere(center=ti.Vector([0, -100.5, -1]), radius=100.0, material=1, color=ti.Vector([0.8, 0.8, 0.8])))
74 | scene.add(Sphere(center=ti.Vector([0, 102.5, -1]), radius=100.0, material=1, color=ti.Vector([0.8, 0.8, 0.8])))
75 | scene.add(Sphere(center=ti.Vector([0, 1, 101]), radius=100.0, material=1, color=ti.Vector([0.8, 0.8, 0.8])))
76 | scene.add(Sphere(center=ti.Vector([-101.5, 0, -1]), radius=100.0, material=1, color=ti.Vector([0.6, 0.0, 0.0])))
77 | scene.add(Sphere(center=ti.Vector([101.5, 0, -1]), radius=100.0, material=1, color=ti.Vector([0.0, 0.6, 0.0])))
78 | scene.add(Sphere(center=ti.Vector([0, -0.2, -1.5]), radius=0.3, material=1, color=ti.Vector([0.8, 0.3, 0.3])))
79 | scene.add(Sphere(center=ti.Vector([-0.8, 0.2, -1]), radius=0.7, material=2, color=ti.Vector([0.6, 0.8, 0.8])))
80 | scene.add(Sphere(center=ti.Vector([0.7, 0, -0.5]), radius=0.5, material=3, color=ti.Vector([1.0, 1.0, 1.0])))
81 | scene.add(Sphere(center=ti.Vector([0.6, -0.3, -2.0]), radius=0.2, material=4, color=ti.Vector([0.8, 0.6, 0.2])))
82 | gui = ti.GUI("Ray Tracing", res=(width, height))
83 | cnt = 0
84 | while gui.running:
85 | render()
86 | cnt += 1
87 | gui.set_image(np.sqrt(canvas.to_numpy() / cnt))
88 | gui.show()
--------------------------------------------------------------------------------
/Lab3 Cloth-simulation/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import taichi as ti
2 | ti.init(ti.gpu)
3 |
4 | n = 128
5 | dt = 1e-3
6 | substep = int(1 / 60 // dt)
7 | quad_size = 1.0 / n
8 | d = 1e2
9 | g = ti.Vector([0, -9.8, 0])
10 | spring_y = 1e3
11 | spring_offsets = ti.Vector.field(2, dtype = int, shape = 6)
12 | spring = ti.types.struct(a = int, b = int, c = int, d = int, e = float)
13 | s = spring.field()
14 | block = ti.root.dense(ti.i, 1)
15 | index = block.dynamic(ti.j, n * n)
16 | index.place(s)
17 | p = ti.Vector.field(3, dtype = float, shape = (n, n))
18 | v = ti.Vector.field(3, dtype = float, shape = (n, n))
19 | f = ti.Vector.field(3, dtype = float, shape = (n, n))
20 | indices = ti.field(dtype = int, shape = (n - 1) * (n - 1) * 6)
21 | vertices = ti.Vector.field(3, dtype = float, shape = n * n)
22 | colors = ti.Vector.field(3, dtype = float, shape = n * n)
23 |
24 | ball_r = 0.3
25 | ball_p = ti.Vector.field(3, dtype = float, shape = 1)
26 | ball_p[0] = [0, 0, 0]
27 |
28 | @ti.kernel
29 | def init_cloth():
30 | #physical
31 | spring_offsets[0] = (0, 2)
32 | spring_offsets[1] = (0, 1)
33 | spring_offsets[2] = (1, 1)
34 | spring_offsets[3] = (2, 0)
35 | spring_offsets[4] = (1, 0)
36 | spring_offsets[5] = (1,-1)
37 | for i, j in ti.ndrange(n, n):
38 | for k in range(6):
39 | ni = i + spring_offsets[k][0]
40 | nj = j + spring_offsets[k][1]
41 | if 0 <= ni < n and 0<= nj < n:
42 | s[0].append(spring(i, j, ni, nj, ti.math.length(p[ni, nj] - p[i, j])))
43 | #rendering
44 | for i, j in ti.ndrange(n - 1, n - 1):
45 | quad_id = i * (n - 1) + j
46 | indices[quad_id * 6 + 0] = i * n + j
47 | indices[quad_id * 6 + 1] = (i + 1) * n + j
48 | indices[quad_id * 6 + 2] = i * n + (j + 1)
49 | indices[quad_id * 6 + 3] = (i + 1) * n + j + 1
50 | indices[quad_id * 6 + 4] = i * n + (j + 1)
51 | indices[quad_id * 6 + 5] = (i + 1) * n + j
52 | for i, j in ti.ndrange(n, n):
53 | if (i // 4 + j // 4) % 2 == 0:
54 | colors[i * n + j] = (0.46, 0.84, 0.92)
55 | else:
56 | colors[i * n + j] = (1, 1, 1)
57 |
58 | @ti.kernel
59 | def start():
60 | offset = ti.Vector([ti.random() - 0.5, 0, ti.random() - 0.5])
61 | for i,j in ti.ndrange(n, n):
62 | p[i, j] = [i * quad_size - 0.5, 0.6, j * quad_size - 0.5] + offset
63 | v[i, j] = [0, 0, 0]
64 | f[i, j] = g
65 | vertices[i * n + j] = p[i, j]
66 |
67 | @ti.kernel
68 | def update():
69 | for i,j in ti.ndrange(n, n):
70 | f[i, j] = g
71 | #v[i, j] *= 0.995
72 | for i in range(s[0].length()):
73 | x = s[0, i].a
74 | y = s[0, i].b
75 | nx = s[0, i].c
76 | ny = s[0, i].d
77 | dist_original = s[0, i].e
78 | dist_current = ti.math.length(p[nx, ny] - p[x, y])
79 | v_relative = (p[nx, ny] - p[x, y]).normalized().dot(v[x, y]) + (p[x, y] - p[nx, ny]).normalized().dot(v[nx, ny])
80 | force = spring_y * (dist_current / dist_original - 1)
81 | force -= d * v_relative
82 |
83 | f[x, y] += force * (p[nx, ny] - p[x, y]).normalized()
84 | f[nx, ny] += force * (p[x, y] - p[nx, ny]).normalized()
85 | for i,j in ti.ndrange(n, n):
86 | v[i, j] += dt * f[i, j]
87 | p[i, j] += dt * v[i, j]
88 | offset_to_center = p[i ,j] - ball_p[0]
89 | if ti.math.length(offset_to_center) <= ball_r:
90 | normal = offset_to_center.normalized()
91 | v[i, j] -= normal * min(v[i, j].dot(normal), 0)
92 | p[i, j] = ball_p[0] + ball_r * normal
93 | vertices[i * n + j] = p[i, j]
94 |
95 | window = ti.ui.Window("Cloth Simulation", (1024, 1024), vsync = True)
96 | canvas = window.get_canvas()
97 | canvas.set_background_color((0, 0, 0))
98 | scene = ti.ui.Scene()
99 | camera = ti.ui.make_camera()
100 | camera.position(0, 0, 3)
101 | camera.lookat(0, 0, 0)
102 | scene.set_camera(camera)
103 | t = 0.0
104 | start()
105 | init_cloth()
106 |
107 | while window.running:
108 | if t >= 1.5 :
109 | t = 0
110 | start()
111 | for i in range(substep):
112 | t += dt
113 | update()
114 | scene.point_light(pos = (0, 1, 2), color = (1, 1, 1))
115 | scene.mesh(vertices, indices = indices, per_vertex_color = colors, two_sided = True)
116 | scene.particles(ball_p, radius = ball_r, color = (0.3, 0.2, 0.5))
117 | canvas.scene(scene)
118 | window.show()
--------------------------------------------------------------------------------
/Lab1 Crash-balls/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import taichi as ti
2 | ti.init(arch=ti.gpu)
3 |
4 | dt = 1e-2
5 | max_num = 64
6 | num = ti.field(dtype = ti.i32, shape=())
7 | wind = ti.field(dtype = ti.f32, shape=())
8 | gravity = ti.field(dtype = ti.f32, shape=())
9 | damp = ti.field(dtype = ti.f32, shape=())
10 | update_model = ti.field(dtype = ti.i32, shape=())
11 | p = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
12 | v = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
13 | f = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
14 | lp = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
15 | lv = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
16 | lf = ti.Vector.field(2, dtype = ti.f32, shape = max_num)
17 | gui = ti.GUI("Crash Balls", (1080, 640), background_color=0xDDDDDD)
18 | gravity[None] = -9.8
19 | damp[None] = 0.15
20 | wind_label = gui.label("Wind")
21 | gravity_label = gui.label("Gravity")
22 | damp_label = gui.label("Damp")
23 |
24 | @ti.kernel
25 | def explicit_update():
26 | for i in range(num[None]):
27 | lp[i] = p[i]
28 | lv[i] = v[i]
29 | lf[i] = f[i]
30 | f[i] = ti.Vector([wind[None], gravity[None]])
31 | v[i] += dt * lf[i]
32 | p[i] += dt * lv[i]
33 |
34 | @ti.kernel
35 | def implicit_update():
36 | for i in range(num[None]):
37 | lp[i] = p[i]
38 | lv[i] = v[i]
39 | lf[i] = f[i]
40 | f[i] = ti.Vector([wind[None], gravity[None]])
41 | v[i] += dt * f[i]
42 | p[i] += dt * v[i]
43 |
44 | @ti.kernel
45 | def semi_implicit_update():
46 | for i in range(num[None]):
47 | lp[i] = p[i]
48 | lv[i] = v[i]
49 | lf[i] = f[i]
50 | f[i] = ti.Vector([wind[None], gravity[None]])
51 | v[i] += dt * lf[i]
52 | p[i] += dt * v[i]
53 |
54 | @ti.kernel
55 | def velocity_welley_update():
56 | for i in range(num[None]):
57 | lp[i] = p[i]
58 | lv[i] = v[i]
59 | lf[i] = f[i]
60 | f[i] = ti.Vector([wind[None], gravity[None]])
61 | p[i] += dt * v[i] + f[i] * dt ** 2 / 2
62 | v[i] += dt * (lf[i] + f[i]) / 2
63 |
64 | @ti.kernel
65 | def runge_kutta2():
66 | for i in range(num[None]):
67 | lp[i] = p[i]
68 | lv[i] = v[i]
69 | lf[i] = f[i]
70 | f[i] = ti.Vector([wind[None], gravity[None]])
71 | v[i] += dt * lf[i]
72 | p[i] += dt * lv[i] / 2
73 | f[i] = ti.Vector([wind[None], gravity[None]])
74 | v[i] += dt * lf[i]
75 | p[i] += dt * lv[i]
76 |
77 | @ti.kernel
78 | def update():
79 | for i in range(num[None]):
80 | for j in ti.static(range(2)):
81 | if p[i][j] < 0:
82 | if ti.math.ceil(-p[i][j]) % 2 == 1:
83 | p[i][j] = ti.math.fract(-p[i][j])
84 | v[i][j] = - (1 - damp[None]) * v[i][j]
85 | else:
86 | p[i][j] = ti.math.fract(p[i][j])
87 | v[i][j] = (1 - damp[None]) * v[i][j]
88 | elif p[i][j] > 1:
89 | if ti.math.floor(p[i][j]) % 2 == 1:
90 | p[i][j] = ti.math.fract(-p[i][j])
91 | v[i][j] = - (1 - damp[None]) * v[i][j]
92 | else:
93 | p[i][j] = ti.math.fract(p[i][j])
94 | v[i][j] = (1 - damp[None]) * v[i][j]
95 | for i in range(num[None]):
96 | for j in range(i + 1, num[None]):
97 | if ti.math.length(p[i] - p[j])< 1e-2:
98 | l = 0.0
99 | r = dt
100 | while(r - l > 1e-5):
101 | m = (l + r) / 2
102 | iPos = p[i] - m * v[i]
103 | jPos = p[j] - m * v[j]
104 | if ti.math.length(iPos - jPos) < 1e-2:
105 | l = m
106 | else:
107 | r = m
108 | p[i] -= r * v[i]
109 | p[j] -= r * v[j]
110 | iTan = (p[j] - p[i]).normalized() * (p[j] - p[i]).normalized().dot(v[i])
111 | jTan = (p[i] - p[j]).normalized() * (p[i] - p[j]).normalized().dot(v[j])
112 | v[i] = v[i] - iTan
113 | v[j] = v[j] - jTan
114 | p[i] += r * v[i]
115 | p[j] += r * v[j]
116 |
117 |
118 | @ti.kernel
119 | def add(xpos:ti.f32, ypos:ti.f32):
120 | if num[None] < max_num:
121 | p[num[None]] = ti.Vector([xpos, ypos])
122 | v[num[None]] = ti.Vector([0, 0])
123 | f[num[None]] = ti.Vector([0, 0])
124 | lp[num[None]] = p[num[None]]
125 | lv[num[None]] = v[num[None]]
126 | lf[num[None]] = f[num[None]]
127 | num[None] += 1
128 |
129 | while gui.running:
130 | if update_model[None] == 0:
131 | explicit_update()
132 | elif update_model[None] == 1:
133 | implicit_update()
134 | elif update_model[None] == 2:
135 | semi_implicit_update()
136 | elif update_model[None] == 3:
137 | velocity_welley_update()
138 | elif update_model[None] == 4:
139 | runge_kutta2()
140 | update()
141 | for e in gui.get_events(ti.GUI.PRESS):
142 | if e.key == 'a' or e.key == ti.GUI.LEFT:
143 | wind[None] -= 0.5
144 | if e.key == 'd' or e.key == ti.GUI.RIGHT:
145 | wind[None] += 0.5
146 | if e.key == 'w':
147 | gravity[None] += 0.5
148 | if e.key == 's':
149 | gravity[None] -= 0.5
150 | if e.key == 'r':
151 | num[None] = 0
152 | if e.key == 'q':
153 | update_model[None] = (update_model[None] + 1) % 5
154 | if e.key == ti.GUI.UP:
155 | damp[None] += 0.05
156 | if e.key == ti.GUI.DOWN:
157 | damp[None] -= 0.05
158 | if e.key == ti.GUI.LMB:
159 | add(e.pos[0], e.pos[1])
160 | if e.key == ti.GUI.ESCAPE:
161 | gui.running = False
162 | for i in range(num[None]):
163 | gui.circle(p[i],color=0x0,radius=5)
164 | wind_label.value = wind[None]
165 | gravity_label.value = gravity[None]
166 | damp_label.value = damp[None]
167 | if update_model[None] == 0:
168 | gui.text("Explicit Euler",(0,1), 16, 0x00)
169 | elif update_model[None] == 1:
170 | gui.text("Implicit Euler",(0,1), 16, 0x00)
171 | elif update_model[None] == 2:
172 | gui.text("Semi-Implicit Euler",(0,1), 16, 0x00)
173 | elif update_model[None] == 3:
174 | gui.text("Velocity Welley",(0,1), 16, 0x00)
175 | elif update_model[None] == 4:
176 | gui.text("Runge Kutta2",(0,1), 16, 0x00)
177 | gui.show()
--------------------------------------------------------------------------------
/Lab8 Stable-fluid/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import taichi as ti
3 | ti.init(arch=ti.gpu)
4 |
5 | res = 512
6 | paused = False
7 | dt = 0.03
8 | p_jacobi_iters = 500
9 | f_strength = 10000.0
10 | curl_strength = 0
11 | dye_decay = 1 - 1 / 60
12 | force_radius = res / 2.0
13 |
14 | class Pair:
15 | def __init__(self, cur, nxt):
16 | self.cur = cur
17 | self.nxt = nxt
18 |
19 | def swap(self):
20 | self.cur, self.nxt = self.nxt, self.cur
21 |
22 | _velocities = ti.Vector.field(2, float, shape=(res, res))
23 | _new_velocities = ti.Vector.field(2, float, shape=(res, res))
24 | velocity_divs = ti.field(float, shape=(res, res))
25 | velocity_curls = ti.field(float, shape=(res, res))
26 | _pressures = ti.field(float, shape=(res, res))
27 | _new_pressures = ti.field(float, shape=(res, res))
28 | _dye_buffer = ti.Vector.field(3, float, shape=(res, res))
29 | _new_dye_buffer = ti.Vector.field(3, float, shape=(res, res))
30 | velocities_pair = Pair(_velocities, _new_velocities)
31 | pressures_pair = Pair(_pressures, _new_pressures)
32 | dyes_pair = Pair(_dye_buffer, _new_dye_buffer)
33 |
34 | class GenMouseData:
35 | def __init__(self):
36 | self.prev_mouse = None
37 | self.prev_color = None
38 |
39 | def __call__(self, gui):
40 | mouse_data = np.zeros(8, dtype=np.float32)
41 | if gui.is_pressed(ti.GUI.LMB):
42 | mxy = np.array(gui.get_cursor_pos(), dtype=np.float32) * res
43 | if self.prev_mouse is None:
44 | self.prev_mouse = mxy
45 | self.prev_color = (np.random.rand(3) * 0.7) + 0.3
46 | else:
47 | mdir = (mxy - self.prev_mouse)
48 | mdir /= np.linalg.norm(mdir) + 1e-5
49 | mouse_data[0], mouse_data[1] = mdir[0], mdir[1]
50 | mouse_data[2], mouse_data[3] = mxy[0], mxy[1]
51 | mouse_data[4:7] = self.prev_color
52 | self.prev_mouse = mxy
53 | else:
54 | self.prev_mouse = None
55 | self.prev_color = None
56 | return mouse_data
57 |
58 | @ti.func
59 | def lerp(vl, vr, frac):
60 | return vl + frac * (vr - vl)
61 |
62 | @ti.func
63 | def sample(qf, u, v):
64 | I = ti.Vector([int(u), int(v)])
65 | I = ti.max(0, ti.min(res - 1, I))
66 | return qf[I]
67 |
68 | @ti.func
69 | def bilerp(vf, p):
70 | u, v = p
71 | s, t = u - 0.5, v - 0.5
72 | iu, iv = ti.floor(s), ti.floor(t)
73 | fu, fv = s - iu, t - iv
74 | a = sample(vf, iu, iv)
75 | b = sample(vf, iu + 1, iv)
76 | c = sample(vf, iu, iv + 1)
77 | d = sample(vf, iu + 1, iv + 1)
78 | return lerp(lerp(a, b, fu), lerp(c, d, fu), fv)
79 |
80 | @ti.func
81 | def backtrace(vf, p, dt_):
82 | v1 = bilerp(vf, p)
83 | p1 = p - 0.5 * dt_ * v1
84 | v2 = bilerp(vf, p1)
85 | p2 = p - 0.75 * dt_ * v2
86 | v3 = bilerp(vf, p2)
87 | p -= dt_ * ((2 / 9) * v1 + (1 / 3) * v2 + (4 / 9) * v3)
88 | return p
89 |
90 | @ti.kernel
91 | def advect(vf: ti.template(), qf: ti.template(), new_qf: ti.template()):
92 | for i, j in vf:
93 | p = ti.Vector([i, j]) + 0.5
94 | p = backtrace(vf, p, dt)
95 | new_qf[i, j] = bilerp(qf, p) * dye_decay
96 |
97 | @ti.kernel
98 | def apply_impulse(vf: ti.template(), dyef: ti.template(), imp_data: ti.types.ndarray()):
99 | g_dir = -ti.Vector([0, 9.8]) * 300
100 | for i, j in vf:
101 | omx, omy = imp_data[2], imp_data[3]
102 | mdir = ti.Vector([imp_data[0], imp_data[1]])
103 | dx, dy = (i + 0.5 - omx), (j + 0.5 - omy)
104 | d2 = dx * dx + dy * dy
105 | factor = ti.exp(-d2 / force_radius)
106 |
107 | a = dyef[i, j].norm()
108 | vf[i, j] += (mdir * f_strength * factor + g_dir * a / (1 + a)) * dt
109 |
110 | if mdir.norm() > 0.5:
111 | dyef[i, j] += ti.exp(-d2 * (4 / (res / 15) ** 2)) * ti.Vector([imp_data[4], imp_data[5], imp_data[6]])
112 |
113 | @ti.kernel
114 | def apply_velocity(vf: ti.template()):
115 | for i, j in vf:
116 | vl = sample(vf, i - 1, j)
117 | vr = sample(vf, i + 1, j)
118 | vb = sample(vf, i, j - 1)
119 | vt = sample(vf, i, j + 1)
120 | vc = sample(vf, i, j)
121 | if i == 0:
122 | vl.x = -vc.x
123 | if i == res - 1:
124 | vr.x = -vc.x
125 | if j == 0:
126 | vb.y = -vc.y
127 | if j == res - 1:
128 | vt.y = -vc.y
129 | velocity_divs[i, j] = (vr.x - vl.x + vt.y - vb.y) * 0.5
130 | velocity_curls[i, j] = (vr.y - vl.y - vt.x + vb.x) * 0.5
131 |
132 | @ti.kernel
133 | def enhance_vorticity(vf: ti.template(), cf: ti.template()):
134 | for i, j in vf:
135 | cl = sample(cf, i - 1, j)
136 | cr = sample(cf, i + 1, j)
137 | cb = sample(cf, i, j - 1)
138 | ct = sample(cf, i, j + 1)
139 | cc = sample(cf, i, j)
140 | force = ti.Vector([abs(ct) - abs(cb), abs(cl) - abs(cr)]).normalized(1e-3)
141 | force *= curl_strength * cc
142 | vf[i, j] = ti.min(ti.max(vf[i, j] + force * dt, -1e3), 1e3)
143 |
144 | @ti.kernel
145 | def pressure_jacobi(pf: ti.template(), new_pf: ti.template()):
146 | for i, j in pf:
147 | pl = sample(pf, i - 1, j)
148 | pr = sample(pf, i + 1, j)
149 | pb = sample(pf, i, j - 1)
150 | pt = sample(pf, i, j + 1)
151 | div = velocity_divs[i, j]
152 | new_pf[i, j] = (pl + pr + pb + pt - div) * 0.25
153 |
154 | def solve_pressure_jacobi():
155 | for _ in range(p_jacobi_iters):
156 | pressure_jacobi(pressures_pair.cur, pressures_pair.nxt)
157 | pressures_pair.swap()
158 |
159 | @ti.kernel
160 | def subtract_gradient(vf: ti.template(), pf: ti.template()):
161 | for i, j in vf:
162 | pl = sample(pf, i - 1, j)
163 | pr = sample(pf, i + 1, j)
164 | pb = sample(pf, i, j - 1)
165 | pt = sample(pf, i, j + 1)
166 | vf[i, j] -= 0.5 * ti.Vector([pr - pl, pt - pb])
167 |
168 | def update(mouse_data):
169 | #Step 1:Advection
170 | advect(velocities_pair.cur, velocities_pair.cur, velocities_pair.nxt)
171 | advect(velocities_pair.cur, dyes_pair.cur, dyes_pair.nxt)
172 | velocities_pair.swap()
173 | dyes_pair.swap()
174 | #Step 2:Applying forces
175 | apply_impulse(velocities_pair.cur, dyes_pair.cur, mouse_data)
176 | apply_velocity(velocities_pair.cur)
177 | enhance_vorticity(velocities_pair.cur, velocity_curls)
178 | #Step 3:Projection
179 | solve_pressure_jacobi()
180 | subtract_gradient(velocities_pair.cur, pressures_pair.cur)
181 |
182 | gui = ti.GUI("Stable Fluid", (res, res))
183 | md_gen = GenMouseData()
184 |
185 | while gui.running:
186 | if gui.get_event(ti.GUI.PRESS):
187 | e = gui.event
188 | if e.key == ti.GUI.ESCAPE:
189 | break
190 | elif e.key == "r":
191 | dyes_pair.cur.fill(0)
192 | elif e.key == "p":
193 | paused = not paused
194 |
195 | if not paused:
196 | mouse_data = md_gen(gui)
197 | update(mouse_data)
198 | gui.set_image(dyes_pair.cur)
199 | gui.show()
--------------------------------------------------------------------------------
/Lab7 Path-tracing/PythonApplication/head.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import taichi as ti
3 |
4 | PI = 3.14159265
5 |
6 | @ti.func
7 | def rand3():
8 | return ti.Vector([ti.random(), ti.random(), ti.random()])
9 |
10 | @ti.func
11 | def random_in_unit_sphere():
12 | p = 2.0 * rand3() - ti.Vector([1, 1, 1])
13 | while p.norm() >= 1.0:
14 | p = 2.0 * rand3() - ti.Vector([1, 1, 1])
15 | return p
16 |
17 | @ti.func
18 | def random_unit_vector():
19 | return random_in_unit_sphere().normalized()
20 |
21 | @ti.func
22 | def to_light_source(hit_point, light_source):
23 | return light_source - hit_point
24 |
25 | @ti.func
26 | def reflect(v, normal):
27 | return v - 2 * v.dot(normal) * normal
28 |
29 | @ti.func
30 | def refract(uv, n, etai_over_etat):
31 | cos_theta = min(n.dot(-uv), 1.0)
32 | r_out_perp = etai_over_etat * (uv + cos_theta * n)
33 | r_out_parallel = -ti.sqrt(abs(1.0 - r_out_perp.dot(r_out_perp))) * n
34 | return r_out_perp + r_out_parallel
35 |
36 | @ti.func
37 | def reflectance(cosine, ref_idx):
38 | # Use Schlick's approximation for reflectance.
39 | r0 = (1 - ref_idx) / (1 + ref_idx)
40 | r0 = r0 * r0
41 | return r0 + (1 - r0) * pow((1 - cosine), 5)
42 |
43 | @ti.data_oriented
44 | class Ray:
45 | def __init__(self, origin, direction):
46 | self.origin = origin
47 | self.direction = direction
48 | def at(self, t):
49 | return self.origin + t * self.direction
50 |
51 | @ti.data_oriented
52 | class Sphere:
53 | def __init__(self, center, radius, material, color):
54 | self.center = center
55 | self.radius = radius
56 | self.material = material
57 | self.color = color
58 |
59 | @ti.func
60 | def hit(self, ray, t_min=0.001, t_max=10e8):
61 | oc = ray.origin - self.center
62 | a = ray.direction.dot(ray.direction)
63 | b = 2.0 * oc.dot(ray.direction)
64 | c = oc.dot(oc) - self.radius * self.radius
65 | discriminant = b * b - 4 * a * c
66 | is_hit = False
67 | front_face = False
68 | root = 0.0
69 | hit_point = ti.Vector([0.0, 0.0, 0.0])
70 | hit_point_normal = ti.Vector([0.0, 0.0, 0.0])
71 | if discriminant > 0:
72 | sqrtd = ti.sqrt(discriminant)
73 | root = (-b - sqrtd) / (2 * a)
74 | if root < t_min or root > t_max:
75 | root = (-b + sqrtd) / (2 * a)
76 | if root >= t_min and root <= t_max:
77 | is_hit = True
78 | else:
79 | is_hit = True
80 | if is_hit:
81 | hit_point = ray.at(root)
82 | hit_point_normal = (hit_point - self.center) / self.radius
83 | # Check which side does the ray hit, we set the hit point normals always point outward from the surface
84 | if ray.direction.dot(hit_point_normal) < 0:
85 | front_face = True
86 | else:
87 | hit_point_normal = -hit_point_normal
88 | return is_hit, root, hit_point, hit_point_normal, front_face, self.material, self.color
89 |
90 | @ti.data_oriented
91 | class Hittable_list:
92 | def __init__(self):
93 | self.objects = []
94 | def add(self, obj):
95 | self.objects.append(obj)
96 | def clear(self):
97 | self.objects = []
98 |
99 | @ti.func
100 | def hit(self, ray, t_min=0.001, t_max=10e8):
101 | closest_t = t_max
102 | is_hit = False
103 | front_face = False
104 | hit_point = ti.Vector([0.0, 0.0, 0.0])
105 | hit_point_normal = ti.Vector([0.0, 0.0, 0.0])
106 | color = ti.Vector([0.0, 0.0, 0.0])
107 | material = 1
108 | for index in ti.static(range(len(self.objects))):
109 | is_hit_tmp, root_tmp, hit_point_tmp, hit_point_normal_tmp, front_face_tmp, material_tmp, color_tmp = self.objects[index].hit(ray, t_min, closest_t)
110 | if is_hit_tmp:
111 | closest_t = root_tmp
112 | is_hit = is_hit_tmp
113 | hit_point = hit_point_tmp
114 | hit_point_normal = hit_point_normal_tmp
115 | front_face = front_face_tmp
116 | material = material_tmp
117 | color = color_tmp
118 | return is_hit, hit_point, hit_point_normal, front_face, material, color
119 |
120 | @ti.func
121 | def hit_shadow(self, ray, t_min=0.001, t_max=10e8):
122 | is_hit_source = False
123 | is_hit_source_temp = False
124 | hitted_dielectric_num = 0
125 | is_hitted_non_dielectric = False
126 | # Compute the t_max to light source
127 | is_hit_tmp, root_light_source, hit_point_tmp, hit_point_normal_tmp, front_face_tmp, material_tmp, color_tmp = \
128 | self.objects[0].hit(ray, t_min)
129 | for index in ti.static(range(len(self.objects))):
130 | is_hit_tmp, root_tmp, hit_point_tmp, hit_point_normal_tmp, front_face_tmp, material_tmp, color_tmp = self.objects[index].hit(ray, t_min, root_light_source)
131 | if is_hit_tmp:
132 | if material_tmp != 3 and material_tmp != 0:
133 | is_hitted_non_dielectric = True
134 | if material_tmp == 3:
135 | hitted_dielectric_num += 1
136 | if material_tmp == 0:
137 | is_hit_source_temp = True
138 | if is_hit_source_temp and (not is_hitted_non_dielectric) and hitted_dielectric_num == 0:
139 | is_hit_source = True
140 | return is_hit_source, hitted_dielectric_num, is_hitted_non_dielectric
141 |
142 |
143 | @ti.data_oriented
144 | class Camera:
145 | def __init__(self, fov=60, aspect_ratio=1.0):
146 | # Camera parameters
147 | self.lookfrom = ti.Vector.field(3, dtype=ti.f32, shape=())
148 | self.lookat = ti.Vector.field(3, dtype=ti.f32, shape=())
149 | self.vup = ti.Vector.field(3, dtype=ti.f32, shape=())
150 | self.fov = fov
151 | self.aspect_ratio = aspect_ratio
152 |
153 | self.cam_lower_left_corner = ti.Vector.field(3, dtype=ti.f32, shape=())
154 | self.cam_horizontal = ti.Vector.field(3, dtype=ti.f32, shape=())
155 | self.cam_vertical = ti.Vector.field(3, dtype=ti.f32, shape=())
156 | self.cam_origin = ti.Vector.field(3, dtype=ti.f32, shape=())
157 | self.reset()
158 |
159 | @ti.kernel
160 | def reset(self):
161 | self.lookfrom[None] = [0.0, 1.0, -5.0]
162 | self.lookat[None] = [0.0, 1.0, -1.0]
163 | self.vup[None] = [0.0, 1.0, 0.0]
164 | theta = self.fov * (PI / 180.0)
165 | half_height = ti.tan(theta / 2.0)
166 | half_width = self.aspect_ratio * half_height
167 | self.cam_origin[None] = self.lookfrom[None]
168 | w = (self.lookfrom[None] - self.lookat[None]).normalized()
169 | u = (self.vup[None].cross(w)).normalized()
170 | v = w.cross(u)
171 | self.cam_lower_left_corner[None] = ti.Vector([-half_width, -half_height, -1.0])
172 | self.cam_lower_left_corner[None] = self.cam_origin[None] - half_width * u - half_height * v - w
173 | self.cam_horizontal[None] = 2 * half_width * u
174 | self.cam_vertical[None] = 2 * half_height * v
175 |
176 | @ti.func
177 | def get_ray(self, u, v):
178 | return Ray(self.cam_origin[None], self.cam_lower_left_corner[None] + u * self.cam_horizontal[None] + v * self.cam_vertical[None] - self.cam_origin[None])
--------------------------------------------------------------------------------
/Lab5 Water-simulation/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import math
2 | import numpy as np
3 | import taichi as ti
4 |
5 | ti.init(ti.gpu)
6 |
7 | screen_res = (800, 800)
8 | screen_to_world_ratio = 20.0
9 | boundary = (screen_res[0]/screen_to_world_ratio, screen_res[1]/screen_to_world_ratio, screen_res[0]/screen_to_world_ratio)
10 | cell_size = 2.51
11 | cell_recpr = 1.0 / cell_size
12 |
13 | def round_up(f, s):
14 | return (math.floor(f * cell_recpr / s) + 1) * s
15 |
16 | grid_size = (round_up(boundary[0], 1), round_up(boundary[1], 1), round_up(boundary[2], 1))
17 |
18 | dim = 3
19 | bg_color = 0x112f41
20 | particle_color = 0x068587
21 | boundary_color = 0xebaca2
22 | num_particles_x = 10
23 | num_particles = 10000
24 | max_num_particles_per_cell = 1000
25 | max_num_neighbors = 1000
26 | time_delta = 1.0 / 20.0
27 | epsilon = 1e-5
28 | particle_radius = 3.0
29 | particle_radius_in_world = particle_radius / screen_to_world_ratio
30 |
31 | h = 1.1
32 | mass = 1.0
33 | rho0 = 1.0
34 | lambda_epsilon = 100.0
35 | pbf_num_iters = 5
36 | corr_deltaQ_coeff = 0.3
37 | corrK = 0.001
38 | neighbor_radius = h * 1.05
39 |
40 | poly6_factor = 315.0 / 64.0 / math.pi
41 | spiky_grad_factor = -45.0 / math.pi
42 |
43 | old_positions = ti.Vector.field(dim, float)
44 | positions = ti.Vector.field(dim, float)
45 | velocities = ti.Vector.field(dim, float)
46 | grid_num_particles = ti.field(int)
47 | particle_num_neighbors = ti.field(int)
48 | particle_neighbors = ti.field(int)
49 | lambdas = ti.field(float)
50 | position_deltas = ti.Vector.field(dim, float)
51 |
52 | ti.root.dense(ti.i, num_particles).place(old_positions, positions, velocities)
53 | grid_snode = ti.root.dense(ti.ijk, grid_size)
54 | grid_snode.place(grid_num_particles)
55 |
56 | grid2particles = ti.field(int, (grid_size + (max_num_particles_per_cell,)))
57 | nb_node = ti.root.dense(ti.i, num_particles)
58 | nb_node.place(particle_num_neighbors)
59 | nb_node.dense(ti.j, max_num_neighbors).place(particle_neighbors)
60 | ti.root.dense(ti.i, num_particles).place(lambdas, position_deltas)
61 |
62 | @ti.kernel
63 | def init():
64 | init_pos = ti.Vector([10.0,10.0,10.0])
65 | cube_size = 20
66 | spacing = 1
67 | num_per_row = (int) (cube_size // spacing) + 1
68 | num_per_floor = num_per_row * num_per_row
69 | for i in range(num_particles):
70 | floor = i // (num_per_floor)
71 | row = (i % num_per_floor) // num_per_row
72 | col = (i % num_per_floor) % num_per_row
73 | positions[i] = ti.Vector([col*spacing, floor*spacing, row*spacing]) + init_pos
74 |
75 | @ti.func
76 | def poly6_value(s, h):
77 | result = 0.0
78 | if 0 < s and s < h:
79 | x = (h * h - s * s) / (h * h * h)
80 | result = poly6_factor * x * x * x
81 | return result
82 |
83 | @ti.func
84 | def spiky_gradient(r, h):
85 | result = ti.Vector([0.0, 0.0, 0.0])
86 | r_len = r.norm()
87 | if 0 < r_len and r_len < h:
88 | x = (h - r_len) / (h * h * h)
89 | g_factor = spiky_grad_factor * x * x
90 | result = r * g_factor / r_len
91 | return result
92 |
93 | @ti.func
94 | def compute_scorr(pos_ji):
95 | x = poly6_value(pos_ji.norm(), h) / poly6_value(corr_deltaQ_coeff * h, h)
96 | x = x * x
97 | x = x * x
98 | return (-corrK) * x
99 |
100 |
101 | @ti.func
102 | def get_cell(pos):
103 | return int(pos * cell_recpr)
104 |
105 | @ti.func
106 | def is_in_grid(c):
107 | return 0 <= c[0] and c[0] < grid_size[0] and 0 <= c[1] and c[
108 | 1] < grid_size[1]
109 |
110 | @ti.func
111 | def confine_position_to_boundary(p):
112 | bmin = particle_radius_in_world
113 | bmax = ti.Vector([boundary[0], boundary[1], boundary[2]]) - particle_radius_in_world
114 | for i in ti.static(range(dim)):
115 | if p[i] <= bmin:
116 | p[i] = bmin + epsilon * ti.random()
117 | elif bmax[i] <= p[i]:
118 | p[i] = bmax[i] - epsilon * ti.random()
119 | return p
120 |
121 | @ti.kernel
122 | def prestep():
123 | for i in positions:
124 | old_positions[i] = positions[i]
125 | for i in positions:
126 | g = ti.Vector([0.0, -10.0, 0.0])
127 | pos, vel = positions[i], velocities[i]
128 | vel += g * time_delta
129 | pos += vel * time_delta
130 | positions[i] = confine_position_to_boundary(pos)
131 |
132 | for i in ti.grouped(grid_num_particles):
133 | grid_num_particles[i] = 0
134 | for i in ti.grouped(particle_neighbors):
135 | particle_neighbors[i] = -1
136 |
137 | for p_i in positions:
138 | cell = get_cell(positions[p_i])
139 | offs = ti.atomic_add(grid_num_particles[cell], 1)
140 | grid2particles[cell, offs] = p_i
141 |
142 | for p_i in positions:
143 | pos_i = positions[p_i]
144 | cell = get_cell(pos_i)
145 | nb_i = 0
146 | for offs in ti.static(ti.grouped(ti.ndrange((-1, 2), (-1, 2),(-1, 2)))):
147 | cell_to_check = cell + offs
148 | if is_in_grid(cell_to_check):
149 | for j in range(grid_num_particles[cell_to_check]):
150 | p_j = grid2particles[cell_to_check, j]
151 | if nb_i < max_num_neighbors and p_j != p_i and (pos_i - positions[p_j]).norm() < neighbor_radius:
152 | particle_neighbors[p_i, nb_i] = p_j
153 | nb_i += 1
154 | particle_num_neighbors[p_i] = nb_i
155 |
156 |
157 | @ti.kernel
158 | def substep():
159 | for p_i in positions:
160 | pos_i = positions[p_i]
161 | grad_i = ti.Vector([0.0, 0.0, 0.0])
162 | sum_gradient_sqr = 0.0
163 | density_constraint = 0.0
164 |
165 | for j in range(particle_num_neighbors[p_i]):
166 | p_j = particle_neighbors[p_i, j]
167 | if p_j < 0:
168 | break
169 | pos_ji = pos_i - positions[p_j]
170 | grad_j = spiky_gradient(pos_ji, h)
171 | grad_i += grad_j
172 | sum_gradient_sqr += grad_j.dot(grad_j)
173 | density_constraint += poly6_value(pos_ji.norm(), h)
174 |
175 | density_constraint = (mass * density_constraint / rho0) - 1.0
176 | sum_gradient_sqr += grad_i.dot(grad_i)
177 | lambdas[p_i] = (-density_constraint) / (sum_gradient_sqr + lambda_epsilon)
178 |
179 | for p_i in positions:
180 | pos_i = positions[p_i]
181 | lambda_i = lambdas[p_i]
182 | pos_delta_i = ti.Vector([0.0, 0.0, 0.0])
183 |
184 | for j in range(particle_num_neighbors[p_i]):
185 | p_j = particle_neighbors[p_i, j]
186 | if p_j < 0:
187 | break
188 | lambda_j = lambdas[p_j]
189 | pos_ji = pos_i - positions[p_j]
190 | scorr_ij = compute_scorr(pos_ji)
191 | pos_delta_i += (lambda_i + lambda_j + scorr_ij) * spiky_gradient(pos_ji, h)
192 |
193 | pos_delta_i /= rho0
194 | position_deltas[p_i] = pos_delta_i
195 |
196 | for i in positions:
197 | positions[i] += position_deltas[i]
198 |
199 | @ti.kernel
200 | def endstep():
201 | for i in positions:
202 | pos = positions[i]
203 | positions[i] = confine_position_to_boundary(pos)
204 |
205 | for i in positions:
206 | velocities[i] = (positions[i] - old_positions[i]) / time_delta
207 |
208 | def update():
209 | prestep()
210 | for cnt in range(pbf_num_iters):
211 | substep()
212 | endstep()
213 |
214 | def T(a):
215 | if dim == 2:
216 | return a
217 | phi, theta = np.radians(28), np.radians(32)
218 | a = a - 0.5
219 | x, y, z = a[:, 0], a[:, 1], a[:, 2]
220 | c, s = np.cos(phi), np.sin(phi)
221 | C, S = np.cos(theta), np.sin(theta)
222 | x, z = x * c + z * s, z * c - x * s
223 | u, v = x, y * C + z * S
224 | return np.array([u, v]).swapaxes(0, 1) + 25
225 |
226 | init()
227 | gui = ti.GUI("Water-simulation", (648, 648), background_color = 0xffffff)
228 | while gui.running and not gui.get_event(gui.ESCAPE):
229 | update()
230 | pos = positions.to_numpy()
231 | gui.circles(T(pos)/100.0, radius=3, color=0x66ccff)
232 | gui.show()
233 |
--------------------------------------------------------------------------------
/Lab4 Dominoes/PythonApplication/PythonApplication.py:
--------------------------------------------------------------------------------
1 | import taichi as ti
2 | from taichi.math import *
3 | ti.init(ti.gpu)
4 |
5 | dt = 1e-2
6 | vertices = ti.Vector.field(3, dtype = float, shape = 8)
7 | indices = ti.field(ti.i32, shape = 13 * 36)
8 |
9 | vertices[0] = (-0.05,-0.1,0.1);vertices[1] = (-0.05,-0.1,-0.1);vertices[2] = (0.05,-0.1,-0.1);vertices[3] = (0.05,-0.1,0.1)
10 | vertices[4] = (-0.05,0.1,0.1);vertices[5] = (-0.05,0.1,-0.1);vertices[6] = (0.05,0.1,-0.1);vertices[7] = (0.05,0.1,0.1)
11 |
12 | indices[0] = 0;indices[1] = 1;indices[2] = 2;indices[3] = 0;indices[4] = 2;indices[5] = 3;indices[6] = 0;indices[7] = 1;indices[8] = 4;
13 | indices[9] = 1;indices[10] = 4;indices[11] = 5;indices[12] = 1;indices[13] = 2;indices[14] = 5;indices[15] = 2;indices[16] = 5;indices[17] = 6
14 | indices[18] = 2;indices[19] = 3;indices[20] = 6;indices[21] = 3;indices[22] = 6;indices[23] = 7;indices[24] = 0;indices[25] = 3;indices[26] = 4
15 | indices[27] = 3;indices[28] = 4;indices[29] = 7;indices[30] = 4;indices[31] = 5;indices[32] = 7;indices[33] = 5;indices[34] = 6;indices[35] = 7
16 |
17 | p = ti.Vector.field(3, dtype = float, shape = 8 * 13)
18 | p0 = ti.Vector.field(3, dtype = float, shape = 8)
19 | p1 = ti.Vector.field(3, dtype = float, shape = 8)
20 | p2 = ti.Vector.field(3, dtype = float, shape = 8)
21 | p3 = ti.Vector.field(3, dtype = float, shape = 8)
22 | p4 = ti.Vector.field(3, dtype = float, shape = 8)
23 | p5 = ti.Vector.field(3, dtype = float, shape = 8)
24 | p6 = ti.Vector.field(3, dtype = float, shape = 8)
25 | p7 = ti.Vector.field(3, dtype = float, shape = 8)
26 | p8 = ti.Vector.field(3, dtype = float, shape = 8)
27 | p9 = ti.Vector.field(3, dtype = float, shape = 8)
28 | p10 = ti.Vector.field(3, dtype = float, shape = 8)
29 | p11 = ti.Vector.field(3, dtype = float, shape = 8)
30 | p12 = ti.Vector.field(3, dtype = float, shape = 8)
31 | w = ti.field(ti.f32, shape = 13)
32 | theta = ti.field(ti.f32, shape = 13)
33 |
34 | w[0] = 1e-3
35 |
36 | @ti.kernel
37 | def init():
38 | for i in range(36, 13 * 36):
39 | indices[i] = indices[i % 36] + i // 36 * 8
40 |
41 | for j in range(8):
42 | p[j] = p0[j] = vertices[j] + ti.Vector((-0.2, 0, - 0.2 - 0.1 * sqrt(3)))
43 | p[j + 8] = p1[j] = vertices[j] + ti.Vector((0, 0, - 0.2 - 0.1 * sqrt(3)))
44 | p[j + 16] = p2[j] = vertices[j] + ti.Vector((0.2, 0, - 0.2 - 0.1 * sqrt(3)))
45 | p[j + 24] = p3[j] = ti.Matrix([[cos(pi/3),0,-sin(pi/3)],[0,1,0],[sin(pi/3),0,cos(pi/3)]]) @ vertices[j] + ti.Vector((0.2 + 0.1 * sqrt(3), 0, - 0.1 - 0.1 * sqrt(3)))
46 | p[j + 32] = p4[j] = ti.Matrix([[cos(2*pi/3),0,-sin(2*pi/3)],[0,1,0],[sin(2*pi/3),0,cos(2*pi/3)]]) @ vertices[j] + ti.Vector((0.2 + 0.1 * sqrt(3), 0, - 0.1))
47 | p[j + 40] = p5[j] = ti.Matrix([[cos(pi),0,-sin(pi)],[0,1,0],[sin(pi),0,cos(pi)]]) @ vertices[j] + ti.Vector((0.2, 0, 0))
48 | p[j + 48] = p6[j] = ti.Matrix([[cos(pi),0,-sin(pi)],[0,1,0],[sin(pi),0,cos(pi)]]) @ vertices[j]
49 | p[j + 56] = p7[j] = ti.Matrix([[cos(pi),0,-sin(pi)],[0,1,0],[sin(pi),0,cos(pi)]]) @ vertices[j] + ti.Vector((-0.2, 0, 0))
50 | p[j + 64] = p8[j] = ti.Matrix([[cos(2*pi/3),0,-sin(2*pi/3)],[0,1,0],[sin(2*pi/3),0,cos(2*pi/3)]]) @ vertices[j] + ti.Vector((- 0.2 - 0.1 * sqrt(3), 0, 0.1))
51 | p[j + 72] = p9[j] = ti.Matrix([[cos(pi/3),0,-sin(pi/3)],[0,1,0],[sin(pi/3),0,cos(pi/3)]]) @ vertices[j] + ti.Vector((- 0.2 - 0.1 * sqrt(3), 0, 0.1 + 0.1 * sqrt(3)))
52 | p[j + 80] = p10[j] = vertices[j] + ti.Vector((- 0.2, 0, 0.2 + 0.1 * sqrt(3)))
53 | p[j + 88] = p11[j] = vertices[j] + ti.Vector((0, 0, 0.2 + 0.1 * sqrt(3)))
54 | p[j + 96] = p12[j] = vertices[j] + ti.Vector((0.2, 0, 0.2 + 0.1 * sqrt(3)))
55 |
56 | @ti.func
57 | def rotate(x:vec3, o:vec3, y:vec3, theta:ti.f32) -> vec3:
58 | left = (x - o).normalized()
59 | up = -(x - o).cross(y - o).normalized()
60 | return o + (x - o).norm() * sin(theta * dt) * up + (x - o).norm() * cos(theta * dt) * left
61 |
62 | @ti.kernel
63 | def update():
64 | p0[0] = rotate(p0[0],p0[3],p0[2],w[0]);p0[1] = p0[0] + p0[2] - p0[3];p0[4] = rotate(p0[4],p0[3],p0[2],w[0])
65 | p0[5] = p0[4] + p0[2] - p0[3];p0[7] = rotate(p0[7],p0[3],p0[2],w[0]);p0[6] = p0[7] + p0[2] - p0[3]
66 |
67 | p1[0] = rotate(p1[0],p1[3],p1[2],w[1]);p1[1] = p1[0] + p1[2] - p1[3];p1[4] = rotate(p1[4],p1[3],p1[2],w[1])
68 | p1[5] = p1[4] + p1[2] - p1[3];p1[7] = rotate(p1[7],p1[3],p1[2],w[1]);p1[6] = p1[7] + p1[2] - p1[3]
69 |
70 | p2[0] = rotate(p2[0],p2[3],p2[2],w[2]);p2[1] = p2[0] + p2[2] - p2[3];p2[4] = rotate(p2[4],p2[3],p2[2],w[2])
71 | p2[5] = p2[4] + p2[2] - p2[3];p2[7] = rotate(p2[7],p2[3],p2[2],w[2]);p2[6] = p2[7] + p2[2] - p2[3]
72 |
73 | p3[0] = rotate(p3[0],p3[3],p3[2],w[3]);p3[1] = p3[0] + p3[2] - p3[3];p3[4] = rotate(p3[4],p3[3],p3[2],w[3])
74 | p3[5] = p3[4] + p3[2] - p3[3];p3[7] = rotate(p3[7],p3[3],p3[2],w[3]);p3[6] = p3[7] + p3[2] - p3[3]
75 |
76 | p4[0] = rotate(p4[0],p4[3],p4[2],w[4]);p4[1] = p4[0] + p4[2] - p4[3];p4[4] = rotate(p4[4],p4[3],p4[2],w[4])
77 | p4[5] = p4[4] + p4[2] - p4[3];p4[7] = rotate(p4[7],p4[3],p4[2],w[4]);p4[6] = p4[7] + p4[2] - p4[3]
78 |
79 | p5[0] = rotate(p5[0],p5[3],p5[2],w[5]);p5[1] = p5[0] + p5[2] - p5[3];p5[4] = rotate(p5[4],p5[3],p5[2],w[5])
80 | p5[5] = p5[4] + p5[2] - p5[3];p5[7] = rotate(p5[7],p5[3],p5[2],w[5]);p5[6] = p5[7] + p5[2] - p5[3]
81 |
82 | p6[0] = rotate(p6[0],p6[3],p6[2],w[6]);p6[1] = p6[0] + p6[2] - p6[3];p6[4] = rotate(p6[4],p6[3],p6[2],w[6])
83 | p6[5] = p6[4] + p6[2] - p6[3];p6[7] = rotate(p6[7],p6[3],p6[2],w[6]);p6[6] = p6[7] + p6[2] - p6[3]
84 |
85 | p7[0] = rotate(p7[0],p7[3],p7[2],w[7]);p7[1] = p7[0] + p7[2] - p7[3];p7[4] = rotate(p7[4],p7[3],p7[2],w[7])
86 | p7[5] = p7[4] + p7[2] - p7[3];p7[7] = rotate(p7[7],p7[3],p7[2],w[7]);p7[6] = p7[7] + p7[2] - p7[3]
87 |
88 | p8[0] = rotate(p8[0],p8[3],p8[2],w[8]);p8[1] = p8[0] + p8[2] - p8[3];p8[4] = rotate(p8[4],p8[3],p8[2],w[8])
89 | p8[5] = p8[4] + p8[2] - p8[3];p8[7] = rotate(p8[7],p8[3],p8[2],w[8]);p8[6] = p8[7] + p8[2] - p8[3]
90 |
91 | p9[0] = rotate(p9[0],p9[3],p9[2],w[9]);p9[1] = p9[0] + p9[2] - p9[3];p9[4] = rotate(p9[4],p9[3],p9[2],w[9])
92 | p9[5] = p9[4] + p9[2] - p9[3];p9[7] = rotate(p9[7],p9[3],p9[2],w[9]);p9[6] = p9[7] + p9[2] - p9[3]
93 |
94 | p10[0] = rotate(p10[0],p10[3],p10[2],w[10]);p10[1] = p10[0] + p10[2] - p10[3];p10[4] = rotate(p10[4],p10[3],p10[2],w[10])
95 | p10[5] = p10[4] + p10[2] - p10[3];p10[7] = rotate(p10[7],p10[3],p10[2],w[10]);p10[6] = p10[7] + p10[2] - p10[3]
96 |
97 | p11[0] = rotate(p11[0],p11[3],p11[2],w[11]);p11[1] = p11[0] + p11[2] - p11[3];p11[4] = rotate(p11[4],p11[3],p11[2],w[11])
98 | p11[5] = p11[4] + p11[2] - p11[3];p11[7] = rotate(p11[7],p11[3],p11[2],w[11]);p11[6] = p11[7] + p11[2] - p11[3]
99 |
100 | p12[0] = rotate(p12[0],p12[3],p12[2],w[12]);p12[1] = p12[0] + p12[2] - p12[3];p12[4] = rotate(p12[4],p12[3],p12[2],w[12])
101 | p12[5] = p12[4] + p12[2] - p12[3];p12[7] = rotate(p12[7],p12[3],p12[2],w[12]);p12[6] = p12[7] + p12[2] - p12[3]
102 |
103 | w[0] = w[0] + (p0[3] - p0[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
104 | w[1] = w[1] + (p1[3] - p1[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
105 | w[2] = w[2] + (p2[3] - p2[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
106 | w[3] = w[3] + (p3[3] - p3[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
107 | w[4] = w[4] + (p4[3] - p4[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
108 | w[5] = w[5] + (p5[3] - p5[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
109 | w[6] = w[6] + (p6[3] - p6[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
110 | w[7] = w[7] + (p7[3] - p7[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
111 | w[8] = w[8] + (p8[3] - p8[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
112 | w[9] = w[9] + (p9[3] - p9[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
113 | w[10] = w[10] + (p10[3] - p10[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
114 | w[11] = w[11] + (p11[3] - p11[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
115 | w[12] = w[12] + (p12[3] - p12[7]).normalized().cross(ti.Vector((0, -1, 0))).norm()
116 |
117 | if (p1[5] - p1[0]).cross(p1[1] - p1[0]).dot(rotate(p0[7],p0[3],p0[2],w[0]) - p1[0]) < 0 or (p1[5] - p1[0]).cross(p1[1] - p1[0]).dot(p0[3] - p1[0]) < 0:
118 | w[1] = w[1] + w[0] * (p0[1] - p0[0]).normalized().dot((p1[1] - p1[0]).normalized())
119 | w[0] = 0
120 |
121 | if (p2[5] - p2[0]).cross(p2[1] - p2[0]).dot(rotate(p1[7],p1[3],p1[2],w[1]) - p2[0]) < 0 or (p2[5] - p2[0]).cross(p2[1] - p2[0]).dot(p1[3] - p2[0]) < 0:
122 | w[2] = w[2] + w[1] * (p1[1] - p1[0]).normalized().dot((p2[1] - p2[0]).normalized())
123 | w[1] = 0
124 |
125 | if (p3[5] - p3[0]).cross(p3[1] - p3[0]).dot(rotate(p2[7],p2[3],p2[2],w[2]) - p3[0]) < 0 or (p3[5] - p3[0]).cross(p2[1] - p2[0]).dot(p1[3] - p2[0]) < 0:
126 | w[3] = w[3] + w[2] * (p2[1] - p2[0]).normalized().dot((p3[1] - p3[0]).normalized())
127 | w[2] = 0
128 |
129 | if (p4[5] - p4[0]).cross(p4[1] - p4[0]).dot(rotate(p3[7],p3[3],p3[2],w[3]) - p4[0]) < 0 or (p4[5] - p4[0]).cross(p4[1] - p4[0]).dot(p3[3] - p4[0]) < 0:
130 | w[4] = w[4] + w[3] * (p3[1] - p3[0]).normalized().dot((p4[1] - p4[0]).normalized())
131 | w[3] = 0
132 |
133 | if (p5[5] - p5[0]).cross(p5[1] - p5[0]).dot(rotate(p4[7],p4[3],p4[2],w[4]) - p5[0]) < 0 or (p5[5] - p5[0]).cross(p5[1] - p5[0]).dot(p4[3] - p5[0]) < 0:
134 | w[5] = w[5] + w[4] * (p4[1] - p4[0]).normalized().dot((p5[1] - p5[0]).normalized())
135 | w[4] = 0
136 |
137 | if (p6[5] - p6[0]).cross(p6[1] - p6[0]).dot(rotate(p5[7],p5[3],p5[2],w[5]) - p6[0]) < 0 or (p6[5] - p6[0]).cross(p6[1] - p6[0]).dot(p5[3] - p6[0]) < 0:
138 | w[6] = w[6] + w[5] * (p5[1] - p5[0]).normalized().dot((p6[1] - p6[0]).normalized())
139 | w[5] = 0
140 |
141 | if (p7[5] - p7[0]).cross(p7[1] - p7[0]).dot(rotate(p6[7],p6[3],p6[2],w[6]) - p7[0]) < 0 or (p7[5] - p7[0]).cross(p7[1] - p7[0]).dot(p6[3] - p7[0]) < 0:
142 | w[7] = w[7] + w[6] * (p6[1] - p6[0]).normalized().dot((p7[1] - p7[0]).normalized())
143 | w[6] = 0
144 |
145 | if (p8[5] - p8[0]).cross(p8[1] - p8[0]).dot(rotate(p7[7],p7[3],p7[2],w[7]) + p7[2] - p7[3] - p8[0]) < 0 or (p8[5] - p8[0]).cross(p8[1] - p8[0]).dot(p7[2] - p8[0]) < 0:
146 | w[8] = w[8] + w[7] * (p7[1] - p7[0]).normalized().dot((p8[1] - p8[0]).normalized())
147 | w[7] = 0
148 |
149 | if (p9[5] - p9[0]).cross(p9[1] - p9[0]).dot(rotate(p8[7],p8[3],p8[2],w[8]) + p8[2] - p8[3] - p9[0]) < 0 or (p9[5] - p9[0]).cross(p9[1] - p9[0]).dot(p8[2] - p9[0]) < 0:
150 | w[9] = w[9] + w[8] * (p8[1] - p8[0]).normalized().dot((p9[1] - p9[0]).normalized())
151 | w[8] = 0
152 |
153 | if (p10[5] - p10[0]).cross(p10[1] - p10[0]).dot(rotate(p9[7],p9[3],p9[2],w[9]) + p9[2] - p9[3] - p10[0]) < 0 or (p10[5] - p10[0]).cross(p10[1] - p10[0]).dot(p9[2] - p10[0]) < 0:
154 | w[10] = w[10] + w[9] * (p9[1] - p9[0]).normalized().dot((p10[1] - p10[0]).normalized())
155 | w[9] = 0
156 |
157 | if (p11[5] - p11[0]).cross(p11[1] - p11[0]).dot(rotate(p10[7],p10[3],p10[2],w[10]) - p11[0]) < 0 or (p11[5] - p11[0]).cross(p11[1] - p11[0]).dot(p10[3] - p11[0]) < 0:
158 | w[11] = w[11] + w[10] * (p10[1] - p10[0]).normalized().dot((p11[1] - p11[0]).normalized())
159 | w[10] = 0
160 |
161 | if (p12[5] - p12[0]).cross(p12[1] - p12[0]).dot(rotate(p11[7],p11[3],p11[2],w[11]) - p12[0]) < 0 or (p12[5] - p12[0]).cross(p12[1] - p12[0]).dot(p11[3] - p12[0]) < 0:
162 | w[12] = w[12] + w[11] * (p11[1] - p11[0]).normalized().dot((p12[1] - p12[0]).normalized())
163 | w[11] = 0
164 |
165 | if rotate(p12[7],p12[3],p12[2],w[12]).y < 0:
166 | w[12] = 0
167 |
168 | for i in range(8):
169 | p[i] = p0[i]
170 | p[8 + i] = p1[i]
171 | p[16 + i] = p2[i]
172 | p[24 + i] = p3[i]
173 | p[32 + i] = p4[i]
174 | p[40 + i] = p5[i]
175 | p[48 + i] = p6[i]
176 | p[56 + i] = p7[i]
177 | p[64 + i] = p8[i]
178 | p[72 + i] = p9[i]
179 | p[80 + i] = p10[i]
180 | p[88 + i] = p11[i]
181 | p[96 + i] = p12[i]
182 |
183 | window = ti.ui.Window("Dominoes", (648, 648), vsync = True)
184 | canvas = window.get_canvas()
185 | canvas.set_background_color((0, 0, 0))
186 | scene = ti.ui.Scene()
187 | camera = ti.ui.Camera()
188 | camera.position(0, 3, 3)
189 | camera.lookat(0, 0, 0)
190 | scene.set_camera(camera)
191 | init()
192 | while window.running:
193 | scene.ambient_light((0.1, 0.1, 0.1))
194 | scene.point_light(pos = (0, 3, -3), color = (1, 1, 1))
195 |
196 | update()
197 | #Combine Mesh
198 | scene.mesh(p, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
199 | #scene.mesh(p0, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
200 | #scene.mesh(p1, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
201 | #scene.mesh(p2, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
202 | #scene.mesh(p3, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
203 | #scene.mesh(p4, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
204 | #scene.mesh(p5, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
205 | #scene.mesh(p6, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
206 | #scene.mesh(p7, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
207 | #scene.mesh(p8, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
208 | #scene.mesh(p9, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
209 | #scene.mesh(p10, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
210 | #scene.mesh(p11, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
211 | #scene.mesh(p12, indices = indices, color = (1, 0.89, 0.8), two_sided = True)
212 | canvas.scene(scene)
213 | window.show()
--------------------------------------------------------------------------------