-
Notifications
You must be signed in to change notification settings - Fork 0
/
matter.go
132 lines (117 loc) · 3.94 KB
/
matter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// molecular is a 3D physics engine written in Go
// Copyright (C) 2023 Kevin Z <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package molecular
// MaterialProps saves the Material properties
type MaterialProps struct {
Brittleness float64 // <https://en.wikipedia.org/wiki/Brittleness>
COR float64 // Coefficient of restitution <https://en.wikipedia.org/wiki/Coefficient_of_restitution>
Density float64 // kg / m^3
Durability int64 // -1 means never break
HeatCap float64 // J / (kg * K) <https://en.wikipedia.org/wiki/Specific_heat_capacity>
FirePoint float64 // The temperature that can cause fire, zero means none
}
// Material represents a unique material.
// You should only handle the pointer of the Material.
// Copying or cloning Material is an illegal operation.
type Material struct {
id string
props MaterialProps
}
func NewMaterial(id string, props MaterialProps) *Material {
return &Material{
id: id,
props: props,
}
}
func (m *Material) Id() string {
return m.id
}
func (m *Material) Props() MaterialProps {
return m.props
}
// MaterialPair represents the status that between two materials
type MaterialPair struct {
// The id of the materials
MatterA, MatterB *Material
// Frictions see: <https://en.wikipedia.org/wiki/Friction>
SCOF, KCOF float64 // the coefficients of static/kinetic friction
}
// CalcNetForce returns the net force of a object after canceled out the friction
// The first argument `natural` is the natural force acting on the material
// The second argument `app` is the application force acting on the object
// Note: All input forces **must be** zero or positive, but the net force may be negative
func (p *MaterialPair) CalcNetForce(natural, app float64, moving bool) float64 {
var friction float64
if moving {
friction = p.KCOF * natural
} else {
friction = p.SCOF * natural
if app <= friction {
return 0
}
}
return app - friction
}
// MaterialSet manages a set of Material and MaterialPair
type MaterialSet struct {
set map[string]*Material
// the key of pairs is smaller first
pairs map[[2]*Material]*MaterialPair
}
func NewMaterialSet() (s *MaterialSet) {
return &MaterialSet{
set: make(map[string]*Material),
pairs: make(map[[2]*Material]*MaterialPair),
}
}
// Add push a Material into the MaterialSet
// If the Material's id is already exists, Add will panic
func (s *MaterialSet) Add(m *Material) {
if m.id == "" {
panic("molecular.MaterialSet: Material's id cannot be empty")
}
if _, ok := s.set[m.id]; ok {
panic("molecular.MaterialSet: Material " + m.id + " is already exists")
}
s.set[m.id] = m
}
func (s *MaterialSet) Get(id string) *Material {
return s.set[id]
}
func (s *MaterialSet) GetPair(a, b *Material) *MaterialPair {
var k [2]*Material
if a.id < b.id {
k[0] = a
k[1] = b
} else {
k[0] = b
k[1] = a
}
return s.pairs[k]
}
// AddPair push a MaterialPair into the MaterialSet
// If the MaterialPair already exists, AddPair will panic
func (s *MaterialSet) AddPair(pair *MaterialPair) {
if pair.MatterA.id > pair.MatterB.id {
pair.MatterA, pair.MatterB = pair.MatterB, pair.MatterA
}
k := [2]*Material{pair.MatterA, pair.MatterB}
if _, ok := s.pairs[k]; ok {
panic("molecular.MaterialSet: The MaterialPair of materials " +
pair.MatterA.id + " and " + pair.MatterA.id + " is already exists")
}
s.pairs[k] = pair
}