This repository has been archived by the owner on Jan 8, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathmesh.cpp
210 lines (176 loc) · 7.38 KB
/
mesh.cpp
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include "types.h"
#include "declarations.h"
#include <string>
//Quat library provided by potatoOS, turns a eular angle into a quaterion
#define _PI 3.14159265358979323846
float rad(float degree) {
return (degree * (_PI / 180));
}
float4 getQuatMul(float4 lhs, float4 rhs) {
return float4(
lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z - lhs.w * rhs.w,
lhs.x * rhs.y + lhs.y * rhs.x + lhs.z * rhs.w - lhs.w * rhs.z,
lhs.x * rhs.z + lhs.z * rhs.x + lhs.w * rhs.y - lhs.y * rhs.w,
lhs.x * rhs.w + lhs.w * rhs.x + lhs.y * rhs.z - lhs.z * rhs.y
);
}
float4 quatFromAngleComponents(float p, float y, float r) {
p = rad(p) * 0.5f;
y = rad(y) * 0.5f;
r = rad(r) * 0.5f;
float4 q_x = float4((float)cos(y), 0, 0, (float)sin(y));
float4 q_y = float4((float)cos(p), 0, (float)sin(p), 0);
float4 q_z = float4((float)cos(r), (float)sin(r), 0, 0);
return getQuatMul(q_x, getQuatMul(q_y, q_z));
}
float4 unfuckQuat(float4 q) {
return float4(q.y, q.z, q.w, q.x);
}
float4 quatFromAngle(QAngle ang) {
return unfuckQuat(quatFromAngleComponents(ang.x, ang.y, ang.z));
}
float3 crossProduct(float3 A, float3 B) {
return float3(
A.y * B.z - A.z * B.y,
A.z * B.x - A.x * B.z,
A.x * B.y - A.y * B.x
);
}
//adds CONVEX mesh for flex
void FLEX_API::addMeshConvex(GarrysMod::Lua::ILuaBase* LUA) {
float4 meshAng = quatFromAngle(LUA->GetAngle(-1));
float4 meshPos = float4(LUA->GetVector(-2), 1.f / 50000.f);
float3 meshMax = LUA->GetVector(-3);
float3 meshMin = LUA->GetVector(-4);
float minFloat[3] = { meshMin.x, meshMin.y, meshMin.z };
float maxFloat[3] = { meshMax.x, meshMax.y, meshMax.z };
size_t tableLen = LUA->ObjLen(-5);
LUA->Pop(4); //pops all stuff above, the table is now at index -1
//add the prop
Prop p = Prop();
p.pos = meshPos;
p.ang = meshAng;
p.lastPos = meshPos;
p.lastAng = meshAng;
p.verts = NvFlexAllocBuffer(flexLibrary, tableLen, sizeof(float4), eNvFlexBufferHost);
float4* hostVerts = (float4*)(NvFlexMap(p.verts, eNvFlexMapWait));
//loop through vertices
for (int i = 0; i < tableLen; i += 3) {
float3 verts[3] = {};
for (int j = 0; j < 3; j++) {
LUA->PushNumber((double)(i + j) + 1.0);
LUA->GetTable(-2);
Vector thisPos = LUA->GetVector();
verts[j] = float3(thisPos);
LUA->Pop(); //pop the pos
}
float3 cross = normalize(crossProduct(verts[1] - verts[0], verts[2] - verts[0]));
float d = cross.x * verts[0].x + cross.y * verts[0].y + cross.z * verts[0].z;
hostVerts[i / 3] = float4(-cross.x, -cross.y, -cross.z, d);
}
//make sure to unmap the verts
NvFlexUnmap(p.verts);
LUA->Pop(); //pop table
//create the triangle mesh
p.meshID = NvFlexCreateConvexMesh(flexLibrary);
NvFlexUpdateConvexMesh(flexLibrary, p.meshID, p.verts, tableLen / 3, minFloat, maxFloat);
// Add data to BUFFERS
mapBuffers();
simBuffers->flags[PropCount] = NvFlexMakeShapeFlags(eNvFlexShapeConvexMesh, true); //always dynamic (props)
simBuffers->geometry[PropCount].convexMesh.mesh = p.meshID;
simBuffers->geometry[PropCount].convexMesh.scale[0] = 1.0f;
simBuffers->geometry[PropCount].convexMesh.scale[1] = 1.0f;
simBuffers->geometry[PropCount].convexMesh.scale[2] = 1.0f;
simBuffers->positions[PropCount] = meshPos;
simBuffers->rotations[PropCount] = meshAng; //dont set rotation to 0,0,0,0 or flex kabooms
simBuffers->prevPositions[PropCount] = meshPos;
simBuffers->prevRotations[PropCount] = meshAng;
unmapBuffers();
props.push_back(p);
PropCount++;
}
//generate a TRIANGLE mesh for flex
void FLEX_API::addMeshConcave(GarrysMod::Lua::ILuaBase* LUA) {
float4 meshAng = quatFromAngle(LUA->GetAngle(-1));
float4 meshPos = float4(LUA->GetVector(-2), 1.f / 50000.f);
float3 meshMax = LUA->GetVector(-3);
float3 meshMin = LUA->GetVector(-4);
float minFloat[3] = { meshMin.x, meshMin.y, meshMin.z };
float maxFloat[3] = { meshMax.x, meshMax.y, meshMax.z };
size_t tableLen = LUA->ObjLen(-5);
LUA->Pop(4); //pops all stuff above, the table is now at index -1
//add the prop
Prop p = Prop();
p.pos = meshPos;
p.ang = meshAng;
p.lastPos = meshPos;
p.lastAng = meshAng;
p.verts = NvFlexAllocBuffer(flexLibrary, tableLen, sizeof(float4), eNvFlexBufferHost);
p.indices = NvFlexAllocBuffer(flexLibrary, tableLen, sizeof(int), eNvFlexBufferHost);
float4* hostVerts = (float4*)(NvFlexMap(p.verts, eNvFlexMapWait));
int* hostIndices = (int*)(NvFlexMap(p.indices, eNvFlexMapWait));
for (int i = 0; i < tableLen; i++) {
LUA->PushNumber((double)i + 1.0); //lua is 1 indexed, C++ is 0 indexed
LUA->GetTable(-2);
Vector thisPos = LUA->GetVector();
float4 vert = float4(thisPos, 0.f);
hostVerts[i] = vert;
hostIndices[i] = i;
//counter clockwise -> clockwise triangle winding
if (i % 3 == 1) {
int host = hostIndices[i];
hostIndices[i] = hostIndices[i - 1];
hostIndices[i - 1] = host;
}
LUA->Pop(); //pop pos
}
LUA->Pop(); //pop table
NvFlexUnmap(p.verts);
NvFlexUnmap(p.indices);
// create the triangle mesh
p.meshID = NvFlexCreateTriangleMesh(flexLibrary);
NvFlexUpdateTriangleMesh(flexLibrary, p.meshID, p.verts, p.indices, tableLen, tableLen / 3, minFloat, maxFloat);
mapBuffers();
simBuffers->flags[PropCount] = NvFlexMakeShapeFlags(eNvFlexShapeTriangleMesh, PropCount != 0); //index 0 is ALWAYS the world
simBuffers->geometry[PropCount].triMesh.mesh = p.meshID;
simBuffers->geometry[PropCount].triMesh.scale[0] = 1.0f;
simBuffers->geometry[PropCount].triMesh.scale[1] = 1.0f;
simBuffers->geometry[PropCount].triMesh.scale[2] = 1.0f;
simBuffers->positions[PropCount] = meshPos;
simBuffers->rotations[PropCount] = meshAng; //dont set rotation to 0,0,0,0 or flex kabooms
simBuffers->prevPositions[PropCount] = meshPos;
simBuffers->prevRotations[PropCount] = meshAng;
unmapBuffers();
props.push_back(p);
PropCount++;
}
//make a capsule mesh collider
void FLEX_API::addMeshCapsule(GarrysMod::Lua::ILuaBase* LUA) {
float4 meshAng = quatFromAngle(LUA->GetAngle(-1));
float4 meshPos = float4(LUA->GetVector(-2), 1.f / 50000.f);
float meshRadius = LUA->GetNumber(-3);
float meshLength = LUA->GetNumber(-4);
LUA->Pop(4); //pops all stuff above, the table is now at index -1
//add the prop
Prop p = Prop();
p.pos = meshPos;
p.ang = meshAng;
p.lastPos = meshPos;
p.lastAng = meshAng;
mapBuffers();
simBuffers->flags[PropCount] = NvFlexMakeShapeFlags(eNvFlexShapeCapsule, true); //index 0 is ALWAYS the world
simBuffers->geometry[PropCount].capsule.halfHeight = meshLength;
simBuffers->geometry[PropCount].capsule.radius = meshRadius;
simBuffers->positions[PropCount] = meshPos;
simBuffers->rotations[PropCount] = meshAng; //dont set rotation to 0,0,0,0 or flex kabooms
simBuffers->prevPositions[PropCount] = meshPos;
simBuffers->prevRotations[PropCount] = meshAng;
unmapBuffers();
props.push_back(p);
PropCount++;
}
//updates position of mesh `id` (50000 is max gmod weight)
void FLEX_API::updateMeshPos(Vector pos, QAngle ang, int id) {
props[id].pos = float4(pos, 1.f / 50000.f);
props[id].ang = quatFromAngle(ang);
}