action-engine-js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +348 -0
- package/actionengine/3rdparty/goblin/goblin.js +9609 -0
- package/actionengine/3rdparty/goblin/goblin.min.js +5 -0
- package/actionengine/camera/actioncamera.js +90 -0
- package/actionengine/camera/cameracollisionhandler.js +69 -0
- package/actionengine/character/actioncharacter.js +360 -0
- package/actionengine/character/actioncharacter3D.js +61 -0
- package/actionengine/core/app.js +430 -0
- package/actionengine/debug/basedebugpanel.js +858 -0
- package/actionengine/display/canvasmanager.js +75 -0
- package/actionengine/display/gl/programmanager.js +570 -0
- package/actionengine/display/gl/shaders/lineshader.js +118 -0
- package/actionengine/display/gl/shaders/objectshader.js +1756 -0
- package/actionengine/display/gl/shaders/particleshader.js +43 -0
- package/actionengine/display/gl/shaders/shadowshader.js +319 -0
- package/actionengine/display/gl/shaders/spriteshader.js +100 -0
- package/actionengine/display/gl/shaders/watershader.js +67 -0
- package/actionengine/display/graphics/actionmodel3D.js +191 -0
- package/actionengine/display/graphics/actionsprite3D.js +230 -0
- package/actionengine/display/graphics/lighting/actiondirectionalshadowlight.js +864 -0
- package/actionengine/display/graphics/lighting/actionlight.js +211 -0
- package/actionengine/display/graphics/lighting/actionomnidirectionalshadowlight.js +862 -0
- package/actionengine/display/graphics/lighting/lightingconstants.js +263 -0
- package/actionengine/display/graphics/lighting/lightmanager.js +789 -0
- package/actionengine/display/graphics/renderableobject.js +44 -0
- package/actionengine/display/graphics/renderers/actionrenderer2D.js +341 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/actionrenderer3D.js +655 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/canvasmanager3D.js +82 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/debugrenderer3D.js +493 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/objectrenderer3D.js +790 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js +266 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js +140 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/waterrenderer3D.js +173 -0
- package/actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js +87 -0
- package/actionengine/display/graphics/texture/proceduraltexture.js +192 -0
- package/actionengine/display/graphics/texture/texturemanager.js +242 -0
- package/actionengine/display/graphics/texture/textureregistry.js +177 -0
- package/actionengine/input/actionscrollablearea.js +1405 -0
- package/actionengine/input/inputhandler.js +1647 -0
- package/actionengine/math/geometry/geometrybuilder.js +161 -0
- package/actionengine/math/geometry/glbexporter.js +364 -0
- package/actionengine/math/geometry/glbloader.js +722 -0
- package/actionengine/math/geometry/modelcodegenerator.js +97 -0
- package/actionengine/math/geometry/triangle.js +33 -0
- package/actionengine/math/geometry/triangleutils.js +34 -0
- package/actionengine/math/mathutils.js +25 -0
- package/actionengine/math/matrix4.js +785 -0
- package/actionengine/math/physics/actionphysics.js +108 -0
- package/actionengine/math/physics/actionphysicsobject3D.js +164 -0
- package/actionengine/math/physics/actionphysicsworld3D.js +238 -0
- package/actionengine/math/physics/actionraycast.js +129 -0
- package/actionengine/math/physics/shapes/actionphysicsbox3D.js +158 -0
- package/actionengine/math/physics/shapes/actionphysicscapsule3D.js +200 -0
- package/actionengine/math/physics/shapes/actionphysicscompoundshape3D.js +147 -0
- package/actionengine/math/physics/shapes/actionphysicscone3D.js +126 -0
- package/actionengine/math/physics/shapes/actionphysicsconvexshape3D.js +72 -0
- package/actionengine/math/physics/shapes/actionphysicscylinder3D.js +117 -0
- package/actionengine/math/physics/shapes/actionphysicsmesh3D.js +74 -0
- package/actionengine/math/physics/shapes/actionphysicsplane3D.js +100 -0
- package/actionengine/math/physics/shapes/actionphysicssphere3D.js +95 -0
- package/actionengine/math/quaternion.js +61 -0
- package/actionengine/math/vector2.js +277 -0
- package/actionengine/math/vector3.js +318 -0
- package/actionengine/math/viewfrustum.js +136 -0
- package/actionengine/network/ACTIONNETREADME.md +810 -0
- package/actionengine/network/client/ActionNetManager.js +802 -0
- package/actionengine/network/client/ActionNetManagerGUI.js +1709 -0
- package/actionengine/network/client/ActionNetManagerP2P.js +1537 -0
- package/actionengine/network/client/SyncSystem.js +422 -0
- package/actionengine/network/p2p/ActionNetPeer.js +142 -0
- package/actionengine/network/p2p/ActionNetTrackerClient.js +623 -0
- package/actionengine/network/p2p/DataConnection.js +282 -0
- package/actionengine/network/p2p/README.md +510 -0
- package/actionengine/network/p2p/example.html +502 -0
- package/actionengine/network/server/ActionNetServer.js +577 -0
- package/actionengine/network/server/ActionNetServerSSL.js +579 -0
- package/actionengine/network/server/ActionNetServerUtils.js +458 -0
- package/actionengine/network/server/SERVERREADME.md +314 -0
- package/actionengine/network/server/package-lock.json +35 -0
- package/actionengine/network/server/package.json +13 -0
- package/actionengine/network/server/start.bat +27 -0
- package/actionengine/network/server/start.sh +25 -0
- package/actionengine/network/server/startwss.bat +27 -0
- package/actionengine/sound/audiomanager.js +1589 -0
- package/actionengine/sound/soundfont/ACTIONSOUNDFONT_README.md +205 -0
- package/actionengine/sound/soundfont/actionparser.js +718 -0
- package/actionengine/sound/soundfont/actionreverb.js +252 -0
- package/actionengine/sound/soundfont/actionsoundfont.js +543 -0
- package/actionengine/sound/soundfont/sf2playerlicence.txt +29 -0
- package/actionengine/sound/soundfont/soundfont.js +2 -0
- package/dist/action-engine.min.js +328 -0
- package/package.json +35 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
// game/character/basecharacter/actioncharacter.js
|
|
2
|
+
|
|
3
|
+
class ActionCharacter extends RenderableObject {
|
|
4
|
+
constructor(camera, game, position) {
|
|
5
|
+
super();
|
|
6
|
+
|
|
7
|
+
this.game = game;
|
|
8
|
+
this.camera = camera;
|
|
9
|
+
|
|
10
|
+
this.height = 6;
|
|
11
|
+
this.scale = 1;
|
|
12
|
+
|
|
13
|
+
this.isFirstPerson = false;
|
|
14
|
+
this.firstPersonHeight = this.height * 0.5;
|
|
15
|
+
|
|
16
|
+
this.basePosition = new Vector3(0, 0, 0); // Ground position
|
|
17
|
+
this.position = new Vector3(0, 40, 0); // Center position
|
|
18
|
+
|
|
19
|
+
this.facingDirection = new Vector3(0, 0, 1);
|
|
20
|
+
this.rotation = 0;
|
|
21
|
+
|
|
22
|
+
this.debugInfo = null;
|
|
23
|
+
|
|
24
|
+
// Camera properties
|
|
25
|
+
this.cameraDistance = 40;
|
|
26
|
+
this.cameraHeight = 10;
|
|
27
|
+
this.cameraPitch = 0;
|
|
28
|
+
this.cameraYaw = 0;
|
|
29
|
+
|
|
30
|
+
// Store pointer position for camera movment
|
|
31
|
+
this.lastPointerX = null;
|
|
32
|
+
this.lastPointerY = null;
|
|
33
|
+
this.swipeStartX = null;
|
|
34
|
+
this.swipeStartY = null;
|
|
35
|
+
|
|
36
|
+
// Create controller
|
|
37
|
+
this.controller = new Goblin.CharacterController(this.game.physicsWorld.getWorld());
|
|
38
|
+
// Get the character body from the controller
|
|
39
|
+
this.body = this.controller.body;
|
|
40
|
+
|
|
41
|
+
if(position){
|
|
42
|
+
this.body.position.set(position.x, position.y, position.z);
|
|
43
|
+
} else {
|
|
44
|
+
this.body.position.set(0, 500, 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add debug tracking
|
|
48
|
+
this.body.debugName = `CharacterBody_${Date.now()}`;
|
|
49
|
+
this.body.createdAt = Date.now();
|
|
50
|
+
|
|
51
|
+
// Get the character body from the controller
|
|
52
|
+
this.body = this.controller.body;
|
|
53
|
+
|
|
54
|
+
// Fine tune physics properties if needed
|
|
55
|
+
this.body.linear_damping = 0.01;
|
|
56
|
+
this.body.angular_damping = 0;
|
|
57
|
+
this.body.friction = 0;
|
|
58
|
+
this.body.restitution = 0.2;
|
|
59
|
+
const worldGravity = game.physicsWorld.getWorld().gravity;
|
|
60
|
+
const gravityMultiplier = 1;
|
|
61
|
+
this.body.setGravity(
|
|
62
|
+
worldGravity.x * gravityMultiplier,
|
|
63
|
+
worldGravity.y * gravityMultiplier,
|
|
64
|
+
worldGravity.z * gravityMultiplier
|
|
65
|
+
);
|
|
66
|
+
this.characterVisualYOffset = 0.75;
|
|
67
|
+
// Add character body to physics world
|
|
68
|
+
this.game.physicsWorld.getWorld().addRigidBody(this.body);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
applyInput(input, deltaTime) {
|
|
72
|
+
if (input.isKeyJustPressed("Numpad0")) {
|
|
73
|
+
this.camera.isDetached = !this.camera.isDetached;
|
|
74
|
+
}
|
|
75
|
+
if (this.camera.isDetached) {
|
|
76
|
+
this.camera.handleDetachedInput(input, deltaTime);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (input.isKeyJustPressed("Action6")) {
|
|
81
|
+
this.isFirstPerson = !this.isFirstPerson;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Handle pointer lock with Action7 (C key)
|
|
85
|
+
if (input.isKeyJustPressed("Action7")) {
|
|
86
|
+
if (document.pointerLockElement) {
|
|
87
|
+
document.exitPointerLock();
|
|
88
|
+
} else {
|
|
89
|
+
document.body.requestPointerLock();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Update camera rotation based on pointer movement when locked
|
|
94
|
+
if (document.pointerLockElement) {
|
|
95
|
+
const mouseSensitivity = 0.01;
|
|
96
|
+
const movement = input.getLockedPointerMovement();
|
|
97
|
+
|
|
98
|
+
if (this.lastPointerX !== movement.x || this.lastPointerY !== movement.y) {
|
|
99
|
+
this.cameraYaw -= movement.x * mouseSensitivity;
|
|
100
|
+
|
|
101
|
+
if (this.isFirstPerson) {
|
|
102
|
+
this.cameraPitch += movement.y * mouseSensitivity;
|
|
103
|
+
} else {
|
|
104
|
+
this.cameraPitch -= movement.y * mouseSensitivity;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.lastPointerX = movement.x;
|
|
108
|
+
this.lastPointerY = movement.y;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
this.cameraPitch = Math.max(-1.57, Math.min(1.57, this.cameraPitch));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Handle swipe camera control
|
|
115
|
+
if (!document.pointerLockElement) {
|
|
116
|
+
const pointerPos = input.getPointerPosition();
|
|
117
|
+
|
|
118
|
+
// Start tracking swipe
|
|
119
|
+
if (input.isPointerJustDown()) {
|
|
120
|
+
this.swipeStartX = pointerPos.x;
|
|
121
|
+
this.swipeStartY = pointerPos.y;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Update camera during swipe
|
|
125
|
+
if (input.isPointerDown() && this.swipeStartX !== null) {
|
|
126
|
+
const deltaX = pointerPos.x - this.swipeStartX;
|
|
127
|
+
const deltaY = pointerPos.y - this.swipeStartY;
|
|
128
|
+
|
|
129
|
+
const swipeSensitivity = 0.005;
|
|
130
|
+
this.cameraYaw -= deltaX * swipeSensitivity;
|
|
131
|
+
|
|
132
|
+
if (this.isFirstPerson) {
|
|
133
|
+
this.cameraPitch += deltaY * swipeSensitivity;
|
|
134
|
+
} else {
|
|
135
|
+
this.cameraPitch -= deltaY * swipeSensitivity;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.cameraPitch = Math.max(-1.57, Math.min(1.57, this.cameraPitch));
|
|
139
|
+
|
|
140
|
+
// Update start position for next frame
|
|
141
|
+
this.swipeStartX = pointerPos.x;
|
|
142
|
+
this.swipeStartY = pointerPos.y;
|
|
143
|
+
} else {
|
|
144
|
+
// Reset swipe tracking when pointer is released
|
|
145
|
+
this.swipeStartX = null;
|
|
146
|
+
this.swipeStartY = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Get input direction relative to camera
|
|
151
|
+
const viewMatrix = this.camera.getViewMatrix();
|
|
152
|
+
const moveDir = new Goblin.Vector3();
|
|
153
|
+
|
|
154
|
+
// Track if we're moving this frame
|
|
155
|
+
let isMovingThisFrame = false;
|
|
156
|
+
|
|
157
|
+
// Get input direction relative to camera
|
|
158
|
+
if (input.isKeyPressed("DirUp")) {
|
|
159
|
+
moveDir.x += viewMatrix.forward.x;
|
|
160
|
+
moveDir.z += viewMatrix.forward.z;
|
|
161
|
+
isMovingThisFrame = true;
|
|
162
|
+
}
|
|
163
|
+
if (input.isKeyPressed("DirDown")) {
|
|
164
|
+
moveDir.x -= viewMatrix.forward.x;
|
|
165
|
+
moveDir.z -= viewMatrix.forward.z;
|
|
166
|
+
isMovingThisFrame = true;
|
|
167
|
+
}
|
|
168
|
+
if (input.isKeyPressed("DirRight")) {
|
|
169
|
+
moveDir.x += viewMatrix.right.x;
|
|
170
|
+
moveDir.z += viewMatrix.right.z;
|
|
171
|
+
isMovingThisFrame = true;
|
|
172
|
+
}
|
|
173
|
+
if (input.isKeyPressed("DirLeft")) {
|
|
174
|
+
moveDir.x -= viewMatrix.right.x;
|
|
175
|
+
moveDir.z -= viewMatrix.right.z;
|
|
176
|
+
isMovingThisFrame = true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Normalize the movement vector if moving diagonally
|
|
180
|
+
if (moveDir.lengthSquared() > 0) {
|
|
181
|
+
moveDir.normalize();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (input.isKeyJustPressed("Action1")) {
|
|
185
|
+
this.controller.wishJump();
|
|
186
|
+
}
|
|
187
|
+
this.controller.handleInput(moveDir);
|
|
188
|
+
|
|
189
|
+
if (input.isKeyJustPressed("ActionDebugToggle")) {
|
|
190
|
+
console.log("Character Debug:", this.controller.getDebugInfo());
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
update(deltaTime) {
|
|
195
|
+
// Physics is now handled in fixed_update, only do non-physics updates here
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
fixed_update(fixedDeltaTime) {
|
|
199
|
+
// Physics and character controller updates should be handled in fixed timestep
|
|
200
|
+
this.controller.update(fixedDeltaTime);
|
|
201
|
+
if (this.body) {
|
|
202
|
+
const pos = this.body.position;
|
|
203
|
+
|
|
204
|
+
this.position.set(pos.x, pos.y, pos.z);
|
|
205
|
+
this.basePosition.set(this.position.x, this.position.y - this.size / 2, this.position.z);
|
|
206
|
+
|
|
207
|
+
// Use yaw for character facing
|
|
208
|
+
this.rotation = this.cameraYaw + Math.PI;
|
|
209
|
+
|
|
210
|
+
this.updateFacingDirection();
|
|
211
|
+
|
|
212
|
+
if (!this.camera.isDetached) {
|
|
213
|
+
// Initialize camera collision handler if needed
|
|
214
|
+
if (!this.cameraCollisionHandler && this.game && this.game.physicsWorld) {
|
|
215
|
+
this.cameraCollisionHandler = new CameraCollisionHandler(this.game.physicsWorld);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (this.isFirstPerson) {
|
|
219
|
+
this.camera.position = this.position.add(new Vector3(0, this.firstPersonHeight, 0));
|
|
220
|
+
|
|
221
|
+
const lookDir = new Vector3(
|
|
222
|
+
Math.sin(this.cameraYaw + Math.PI) * Math.cos(this.cameraPitch),
|
|
223
|
+
-Math.sin(this.cameraPitch),
|
|
224
|
+
Math.cos(this.cameraYaw + Math.PI) * Math.cos(this.cameraPitch)
|
|
225
|
+
);
|
|
226
|
+
this.camera.target = this.camera.position.add(lookDir);
|
|
227
|
+
} else {
|
|
228
|
+
const cameraOffset = new Vector3(
|
|
229
|
+
Math.sin(this.cameraYaw) * Math.cos(this.cameraPitch) * this.cameraDistance,
|
|
230
|
+
-Math.sin(this.cameraPitch) * this.cameraDistance + this.cameraHeight,
|
|
231
|
+
Math.cos(this.cameraYaw) * Math.cos(this.cameraPitch) * this.cameraDistance
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
// Calculate desired camera position without collision
|
|
235
|
+
const desiredCameraPosition = this.position.add(cameraOffset);
|
|
236
|
+
|
|
237
|
+
// Apply camera collision if handler exists
|
|
238
|
+
if (this.cameraCollisionHandler) {
|
|
239
|
+
// Adjust camera position for collisions - no smoothing
|
|
240
|
+
this.camera.position = this.cameraCollisionHandler.adjustCameraPosition(
|
|
241
|
+
this.position,
|
|
242
|
+
desiredCameraPosition,
|
|
243
|
+
1.6 // Camera collision radius
|
|
244
|
+
);
|
|
245
|
+
} else {
|
|
246
|
+
// Fall back to original behavior if no collision handler
|
|
247
|
+
this.camera.position = desiredCameraPosition;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
this.camera.target = this.position.add(new Vector3(0, this.height / 2, 0));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Store debug info
|
|
256
|
+
if (this.controller) {
|
|
257
|
+
this.debugInfo = this.controller.getDebugInfo();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Standard method for renderable objects
|
|
262
|
+
updateVisual() {
|
|
263
|
+
this.triangles = this.getCharacterModelTriangles();
|
|
264
|
+
this.updateModelMatrix();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
updateModelMatrix() {
|
|
268
|
+
// Calculate the model matrix based on position and facing direction
|
|
269
|
+
const angle = Math.atan2(this.facingDirection.x, this.facingDirection.z);
|
|
270
|
+
this.modelMatrix = Matrix4.create();
|
|
271
|
+
|
|
272
|
+
// Apply rotation around character's local origin first
|
|
273
|
+
Matrix4.rotateY(this.modelMatrix, this.modelMatrix, angle);
|
|
274
|
+
|
|
275
|
+
// Then translate to world position
|
|
276
|
+
Matrix4.translate(this.modelMatrix, this.modelMatrix, [this.position.x, this.position.y, this.position.z]);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
// Original method - mainly used by 2d renderer
|
|
281
|
+
getCharacterModelTriangles() {
|
|
282
|
+
function transformVertexWithSkin(vertex, vertexIndex, triangle, skin) {
|
|
283
|
+
if (!triangle.jointData || !triangle.weightData) {
|
|
284
|
+
return vertex;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const finalPosition = new Vector3(0, 0, 0);
|
|
288
|
+
const joints = triangle.jointData[vertexIndex];
|
|
289
|
+
const weights = triangle.weightData[vertexIndex];
|
|
290
|
+
let totalWeight = 0;
|
|
291
|
+
|
|
292
|
+
for (let i = 0; i < 4; i++) {
|
|
293
|
+
const weight = weights[i];
|
|
294
|
+
if (weight > 0) {
|
|
295
|
+
totalWeight += weight;
|
|
296
|
+
const jointMatrix = skin.jointMatrices[joints[i]];
|
|
297
|
+
if (jointMatrix) {
|
|
298
|
+
const transformed = Vector3.transformMat4(vertex, jointMatrix);
|
|
299
|
+
finalPosition.x += transformed.x * weight;
|
|
300
|
+
finalPosition.y += transformed.y * weight;
|
|
301
|
+
finalPosition.z += transformed.z * weight;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (totalWeight > 0 && Math.abs(totalWeight - 1.0) > 0.001) {
|
|
307
|
+
finalPosition.x /= totalWeight;
|
|
308
|
+
finalPosition.y /= totalWeight;
|
|
309
|
+
finalPosition.z /= totalWeight;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return finalPosition;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function applyTransform(vertex, transform) {
|
|
316
|
+
return Vector3.transformMat4(vertex, transform);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Calculate model orientation transform based on facing direction
|
|
320
|
+
const angle = Math.atan2(this.facingDirection.x, this.facingDirection.z);
|
|
321
|
+
const modelTransform = Matrix4.create();
|
|
322
|
+
|
|
323
|
+
// Position the character at the correct world position
|
|
324
|
+
Matrix4.translate(modelTransform, modelTransform, [this.position.x, this.position.y + this.characterVisualYOffset, this.position.z]);
|
|
325
|
+
|
|
326
|
+
Matrix4.rotateY(modelTransform, modelTransform, angle);
|
|
327
|
+
const transformedTriangles = [];
|
|
328
|
+
const skin = this.characterModel.skins[0];
|
|
329
|
+
|
|
330
|
+
// Process each triangle in the model
|
|
331
|
+
for (const triangle of this.characterModel.triangles) {
|
|
332
|
+
// Apply skinning to each vertex
|
|
333
|
+
const skinnedVertices = [];
|
|
334
|
+
for (let i = 0; i < triangle.vertices.length; i++) {
|
|
335
|
+
skinnedVertices.push(transformVertexWithSkin(triangle.vertices[i], i, triangle, skin));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Apply model transform to skinned vertices
|
|
339
|
+
const transformedVerts = [];
|
|
340
|
+
for (let i = 0; i < skinnedVertices.length; i++) {
|
|
341
|
+
transformedVerts.push(applyTransform(skinnedVertices[i], modelTransform));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Create final transformed triangle
|
|
345
|
+
transformedTriangles.push(
|
|
346
|
+
new Triangle(transformedVerts[0], transformedVerts[1], transformedVerts[2], triangle.color)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return transformedTriangles;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
updateFacingDirection() {
|
|
354
|
+
this.facingDirection = new Vector3(
|
|
355
|
+
Math.sin(this.rotation), // X component
|
|
356
|
+
0, // Y component (flat on xz plane)
|
|
357
|
+
Math.cos(this.rotation) // Z component
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// actionengine/character/actioncharacter3D.js
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* A basic character controller wrapper.
|
|
5
|
+
* It is based on GoblinPhysics spring based CharacterController.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
class ActionCharacter3D extends ActionCharacter {
|
|
9
|
+
constructor(camera, game, position) {
|
|
10
|
+
super(camera, game, position);
|
|
11
|
+
|
|
12
|
+
// Set additional properties needed by the parent class
|
|
13
|
+
this.firstPersonHeight = this.height * 0.5;
|
|
14
|
+
|
|
15
|
+
// Create a capsule physics model
|
|
16
|
+
this.characterModel = new ActionPhysicsCapsule3D(
|
|
17
|
+
this.game.physicsWorld,
|
|
18
|
+
2,
|
|
19
|
+
6,
|
|
20
|
+
0, // mass
|
|
21
|
+
new Vector3(0, 0, 0), // position
|
|
22
|
+
"#4488FF" // character color
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
console.log("[ActionCharacter3D] Initialized");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fixed_update(fixedDeltaTime) {
|
|
29
|
+
// Call parent's fixed_update for physics
|
|
30
|
+
super.fixed_update(fixedDeltaTime);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
update(deltaTime) {
|
|
34
|
+
super.update(deltaTime);
|
|
35
|
+
|
|
36
|
+
// Update the visual representation to match the character controller
|
|
37
|
+
if (this.characterModel && this.body) {
|
|
38
|
+
// Copy position from character controller to our visual model
|
|
39
|
+
this.characterModel.body.position.x = this.body.position.x;
|
|
40
|
+
this.characterModel.body.position.y = this.body.position.y;
|
|
41
|
+
this.characterModel.body.position.z = this.body.position.z;
|
|
42
|
+
|
|
43
|
+
// Update capsule rotation based on character facing direction
|
|
44
|
+
const angle = Math.atan2(this.facingDirection.x, this.facingDirection.z);
|
|
45
|
+
|
|
46
|
+
// First create quaternion using ActionEngine's Quaternion class
|
|
47
|
+
const engineQuat = Quaternion.fromAxisAngle(new Vector3(0, 1, 0), angle);
|
|
48
|
+
|
|
49
|
+
// Directly set the rotation components on the body's rotation quaternion
|
|
50
|
+
this.characterModel.body.rotation.x = engineQuat.x;
|
|
51
|
+
this.characterModel.body.rotation.y = engineQuat.y;
|
|
52
|
+
|
|
53
|
+
// Mark the character model as dirty since we manually updated its position and rotation
|
|
54
|
+
if (typeof this.characterModel.markVisualDirty === 'function') {
|
|
55
|
+
this.characterModel.markVisualDirty();
|
|
56
|
+
}
|
|
57
|
+
this.characterModel.body.rotation.z = engineQuat.z;
|
|
58
|
+
this.characterModel.body.rotation.w = engineQuat.w;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|