Commit 340f2a4d authored by Master Q's avatar Master Q

物理世界创建

parent 6e17550e
...@@ -12452,6 +12452,18 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -12452,6 +12452,18 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
dirLight.target.position.set(0, 0, 0); dirLight.target.position.set(0, 0, 0);
this.scene.add(dirLight); this.scene.add(dirLight);
this.scene.add(new THREE.DirectionalLightHelper(dirLight)); this.scene.add(new THREE.DirectionalLightHelper(dirLight));
dirLight.castShadow = true;
console.log(dirLight.shadow);
dirLight.shadow.mapSize.width = 1024; // 2的 n次幂 数值越高 细节越高
dirLight.shadow.mapSize.height = 1024;
dirLight.shadow.camera.near = 0.3;
dirLight.shadow.camera.far = 60;
dirLight.shadow.camera.top = 40;
dirLight.shadow.camera.left = 44;
dirLight.shadow.camera.bottom = -28;
dirLight.shadow.camera.right = -44;
dirLight.shadow.radius = 4;
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
let renderer = this.renderer; let renderer = this.renderer;
// 开启阴影 // 开启阴影
renderer.shadowMap.enabled = true; renderer.shadowMap.enabled = true;
...@@ -12486,11 +12498,13 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -12486,11 +12498,13 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
console.log(this.ammoPhysicWorld); console.log(this.ammoPhysicWorld);
const boxGeometry = new THREE.BoxGeometry(1, 1, 1); const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshLambertMaterial({ const material = new THREE.MeshLambertMaterial({
// wireframe: true // wireframe: true,
map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg')
}); });
material.color = new THREE.Color(0xffffff * Math.random()); material.color = new THREE.Color(0xffffff * Math.random());
const boxMesh = new THREE.Mesh(boxGeometry, material); const boxMesh = new THREE.Mesh(boxGeometry, material);
boxMesh.position.set(0, 20, 0); boxMesh.position.set(0, 20, 0);
boxMesh.castShadow = true;
this.scene.add(boxMesh); this.scene.add(boxMesh);
this.ammoPhysicWorld.addMesh(boxMesh, { this.ammoPhysicWorld.addMesh(boxMesh, {
mass: 1, mass: 1,
...@@ -12523,7 +12537,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -12523,7 +12537,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
const Planegeometry = new THREE.PlaneBufferGeometry(terrainWidthExtents, terrainDepthExtents, terrainWidth - 1, terrainDepth - 1); const Planegeometry = new THREE.PlaneBufferGeometry(terrainWidthExtents, terrainDepthExtents, terrainWidth - 1, terrainDepth - 1);
Planegeometry.rotateX(-Math.PI / 2); Planegeometry.rotateX(-Math.PI / 2);
const vertices = Planegeometry.attributes.position.array; const vertices = Planegeometry.attributes.position.array;
console.log(vertices); // console.log(vertices)
// i < l // i < l
for (var i = 0, j = 0, l = vertices.length; j < l; i++, j += 3) { for (var i = 0, j = 0, l = vertices.length; j < l; i++, j += 3) {
// j + 1 because it is the y component that we modify // j + 1 because it is the y component that we modify
...@@ -12534,6 +12548,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -12534,6 +12548,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
Planegeometry.computeVertexNormals(); Planegeometry.computeVertexNormals();
const groundMaterial = new THREE.MeshPhongMaterial({ color: 0xC7C7C7 }); const groundMaterial = new THREE.MeshPhongMaterial({ color: 0xC7C7C7 });
const terrainMesh = new THREE.Mesh(Planegeometry, groundMaterial); const terrainMesh = new THREE.Mesh(Planegeometry, groundMaterial);
terrainMesh.receiveShadow = true;
this.scene.add(terrainMesh); this.scene.add(terrainMesh);
// This parameter is not really used, since we are using PHY_FLOAT height data type and hence it is ignored // This parameter is not really used, since we are using PHY_FLOAT height data type and hence it is ignored
var heightScale = 1; var heightScale = 1;
...@@ -12705,6 +12720,7 @@ function createElement(type, className, style, events) { ...@@ -12705,6 +12720,7 @@ function createElement(type, className, style, events) {
for (let k in events) { for (let k in events) {
dom.addEventListener(k, events[k]); dom.addEventListener(k, events[k]);
} }
return dom;
} }
class Vehicle extends THREE.Object3D { class Vehicle extends THREE.Object3D {
constructor(pos, quat) { constructor(pos, quat) {
...@@ -12755,6 +12771,13 @@ class Vehicle extends THREE.Object3D { ...@@ -12755,6 +12771,13 @@ class Vehicle extends THREE.Object3D {
var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength); var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength);
// this.fixedChassicMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength) // this.fixedChassicMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength)
this.fixedChassicMesh = this.chassisMesh.add(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materialDynamic)); this.fixedChassicMesh = this.chassisMesh.add(new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), materialDynamic));
this.sppedBoard = createElement('div', 'speedboard', {
position: 'fixed',
backgroundColor: 'yellow',
padding: '3px 20px',
left: "0px",
bottom: "0px"
});
createElement('div', 'left', { createElement('div', 'left', {
position: 'fixed', position: 'fixed',
width: '80px', width: '80px',
...@@ -12882,12 +12905,14 @@ class Vehicle extends THREE.Object3D { ...@@ -12882,12 +12905,14 @@ class Vehicle extends THREE.Object3D {
t.rotateZ(Math.PI / 2); t.rotateZ(Math.PI / 2);
var mesh = new THREE.Mesh(t, materialInteractive); var mesh = new THREE.Mesh(t, materialInteractive);
mesh.add(new THREE.Mesh(new THREE.BoxGeometry(width * 1.5, radius * 1.75, radius * .25, 1, 1, 1), materialInteractive)); mesh.add(new THREE.Mesh(new THREE.BoxGeometry(width * 1.5, radius * 1.75, radius * .25, 1, 1, 1), materialInteractive));
mesh.castShadow = true;
this.add(mesh); this.add(mesh);
return mesh; return mesh;
} }
createChassisMesh(w, l, h) { createChassisMesh(w, l, h) {
var shape = new THREE.BoxGeometry(w, l, h, 1, 1, 1); var shape = new THREE.BoxGeometry(w, l, h, 1, 1, 1);
var mesh = new THREE.Mesh(shape, materialInteractive); var mesh = new THREE.Mesh(shape, materialInteractive);
mesh.castShadow = true;
this.add(mesh); this.add(mesh);
return mesh; return mesh;
} }
...@@ -12917,7 +12942,7 @@ class Vehicle extends THREE.Object3D { ...@@ -12917,7 +12942,7 @@ class Vehicle extends THREE.Object3D {
const vehicle = this.raycastVehicle; const vehicle = this.raycastVehicle;
const tuning = this.btVehicleTuning; const tuning = this.btVehicleTuning;
var speed = vehicle.getCurrentSpeedKmHour(); var speed = vehicle.getCurrentSpeedKmHour();
// speedometer.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h'; this.sppedBoard.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h';
let breakingForce = 0; let breakingForce = 0;
let engineForce = 0; let engineForce = 0;
const isAccelerating = this.actions.acceleration || keyboardState_1.KeyBoardStateStore.isPressed('w'); const isAccelerating = this.actions.acceleration || keyboardState_1.KeyBoardStateStore.isPressed('w');
...@@ -12937,6 +12962,8 @@ class Vehicle extends THREE.Object3D { ...@@ -12937,6 +12962,8 @@ class Vehicle extends THREE.Object3D {
} }
} }
} }
// 最大速度
if (speed < 80) {
if (isAccelerating) { if (isAccelerating) {
if (speed < -1) { if (speed < -1) {
breakingForce = maxBreakingForce; breakingForce = maxBreakingForce;
...@@ -12972,6 +12999,7 @@ class Vehicle extends THREE.Object3D { ...@@ -12972,6 +12999,7 @@ class Vehicle extends THREE.Object3D {
} }
} }
} }
}
vehicle.applyEngineForce(engineForce, BACK_LEFT); vehicle.applyEngineForce(engineForce, BACK_LEFT);
vehicle.applyEngineForce(engineForce, BACK_RIGHT); vehicle.applyEngineForce(engineForce, BACK_RIGHT);
// brake 刹车 // brake 刹车
...@@ -14266,7 +14294,7 @@ class KeyBoardState extends EventDispatcher_1.EventDispatcher { ...@@ -14266,7 +14294,7 @@ class KeyBoardState extends EventDispatcher_1.EventDispatcher {
this.removeEventListener(key + '-down', callback); this.removeEventListener(key + '-down', callback);
} }
isPressed(key) { isPressed(key) {
return this.keyState[key.toUpperCase()]; return this.keyState[key.toUpperCase()] || this.keyState[key.toLocaleLowerCase()];
} }
} }
exports.KeyBoardState = KeyBoardState; exports.KeyBoardState = KeyBoardState;
This diff is collapsed.
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
"author": "lightfish", "author": "lightfish",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/three": "^0.143.0", "@types/three": "^0.144.0",
"oimo": "^1.0.9", "oimo": "^1.0.9",
"three": "^0.143.0", "three": "^0.144.0",
"ts-loader": "^9.3.1", "ts-loader": "^9.3.1",
"typescript": "^4.7.4", "typescript": "^4.7.4",
"webpack": "^5.74.0", "webpack": "^5.74.0",
......
This diff is collapsed.
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
</head> </head>
<body> <body>
<!-- 这里的 bundle 就是 webpack 临时打包出来 --> <!-- 这里的 bundle 就是 webpack 临时打包出来 -->
<script src="//yun.duiba.com.cn/aurora/assets/5feda82574ac6db79f09540a8d24d09ff29ec9c9.js"></script> <script src="//yun.duiba.com.cn/aurora/assets/869d3b0ec6db510a351a8ae857a282e5e0b3eab4.js"></script>
<script> <script>
window.addEventListener("load", function () { window.addEventListener("load", function () {
console.log('load') console.log('load')
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import * as THREE from "three"
interface RigidBodyConfig {
mass: number,
friction: number // 摩擦力
restitution: number // 弹性
pos: THREE.Vector3
qua: THREE.Quaternion
scaleNum: number
}
/**
* 创建物理
* @param physicsShape
* @param cfg
* @returns
*/
export function createRigidBody(physicsShape: Ammo.btCollisionShape, cfg: Partial<RigidBodyConfig> = {
mass: 1
}) {
const {
mass,
friction,
restitution,
pos,
qua
} = cfg
const transfrom = new Ammo.btTransform()
transfrom.setIdentity()
pos && transfrom.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z))
qua && transfrom.setRotation(new Ammo.btQuaternion(qua.x, qua.y, qua.z, qua.w))
const motionState = new Ammo.btDefaultMotionState(transfrom)
const localInertia = new Ammo.btVector3(0,0,0)
physicsShape.calculateLocalInertia(mass, localInertia)
const rbInfo = new Ammo.btRigidBodyConstructionInfo(
mass,
motionState,
physicsShape,
localInertia
)
const rigidBody = new Ammo.btRigidBody(rbInfo)
friction && rigidBody.setFriction(friction)
restitution && rigidBody.setRestitution(restitution)
if (mass > 0) {
rigidBody.setActivationState(4)
}
return rigidBody
}
const defaultMatrix3 = new THREE.Matrix3()
export function createRigidBodyByThreeObject(obj3: THREE.Mesh, cfg: Partial<RigidBodyConfig>) {
const {
mass,
friction,
restitution,
pos,
qua,
scaleNum = 1
} = cfg
// 反正每一帧都回去改, 所以无所谓的
pos && obj3.position.copy(pos)
qua && obj3.quaternion.copy(qua)
if (scaleNum) {
// obj3.scale.set(scaleNum, scaleNum, scaleNum)
obj3.position.multiplyScalar(scaleNum)
}
defaultMatrix3.setFromMatrix4(obj3.matrixWorld)
const body = createTriangleShapeByGeometry(obj3.geometry, {
...cfg,
pos: obj3.position, //.applyMatrix3(defaultMatrix3), //(new THREE.Vector3()).applyMatrix4(obj3.matrixWorld),
qua: obj3.quaternion
})
body.meshData = obj3
obj3.geometry.userData.physicsBody = body
return body
}
function tt(n: number, vertices: ArrayLike<number>, s: number) {
const index = n * 3
// console.log(n)
// console.log(vertices[index] * s,
// vertices[index + 1] * s,
// vertices[index + 2] * s)
return new Ammo.btVector3(
vertices[index] * s,
vertices[index + 1] * s,
vertices[index + 2] * s
)
}
export function createTriangleShapeByGeometry(geometry: THREE.BufferGeometry, cfg: Partial<RigidBodyConfig>) {
const mesh = new Ammo.btTriangleMesh(true, true)
const vertices = geometry.attributes.position.array
const n = cfg.scaleNum || 1
const indexArr = geometry.index.array
for (let i = 0; i < indexArr.length; i += 3) {
const trianglePoint = ([0, 1, 2] as const).map(num => {
return tt(indexArr[i + num], vertices, n)
})
mesh.addTriangle(
// @ts-ignore
...trianglePoint
)
}
const shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true)
// ??
shape.setMargin(0.05)
return createRigidBody(shape, cfg)
}
export function createAmmoTerrainBody(positionArray: Float32Array, segmentArgs: number = 3, scale: number = 100) {
const verties = positionArray
const heightData: Record<string, Record<string, string>> = {}
const segment = segmentArgs
let terrainMinHeight = 0
let terrainMaxHeight = 0
let terrainMinX = 0
let terrainMaxX = 0
let terrainMinZ = 0
let terrainMaxZ = 0
for (let i = 0; i < verties.length; i+=3) {
const x = verties[i] * scale
const y = verties[i + 1] * scale
const z = verties[i + 2] * scale
const _x = Math.floor(x / segment)
const _z = Math.floor(z / segment)
// @ts-ignore
const arr = (heightData[_z] || (heightData[_z] = {}))
const pre = arr[_x] || '0/0/0';
const spt = pre.split('/');
const currSum = parseFloat(spt[0]) + y;
const currCount = parseFloat(spt[1]) + 1;
const currA = currSum / currCount
terrainMinHeight = currA < terrainMinHeight ? currA : terrainMinHeight
terrainMaxHeight = currA > terrainMaxHeight ? currA : terrainMaxHeight
terrainMinX = x < terrainMinX ? x : terrainMinX
terrainMaxX = x > terrainMaxX ? x : terrainMaxX
terrainMinZ = z < terrainMinZ ? z : terrainMinZ
terrainMaxZ = z > terrainMaxZ ? z : terrainMaxZ
arr[_x] = `${currSum}/${currCount}/${currA}`
}
const terrainWidthExtents = terrainMaxX - terrainMinX
const terrainDepthExtents = terrainMaxZ - terrainMinZ
const terrainDepthOfKeys = Object.keys(heightData).sort((a, b) => Number(a) - Number(b))
const terrainWidthOfKeys = Object.keys(heightData['0']).sort((a, b) => Number(a) - Number(b))
const terrainWidth = terrainWidthOfKeys.length
const terrainDepth = terrainDepthOfKeys.length
const planMesh = new THREE.Mesh(
new THREE.PlaneGeometry( terrainWidthExtents,terrainDepthExtents, terrainWidth - 1, terrainDepth -1),
new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true
})
)
planMesh.rotateX( - Math.PI / 2 );
const vertices = planMesh.geometry.attributes.position.array;
console.log(planMesh.geometry.attributes.position)
// i < l
// let ii = 0;
const v = Object.keys(heightData).sort((a, b) => Number(a) - Number(b));
console.log(vertices)
for ( var i = 0; i < v.length; i ++) {
const u = heightData[v[i]]
const k = Object.keys(u).sort((a, b) => Number(a) - Number(b))
for( let j = 0; j < k.length; j++) {
const q = u[k[j]]
const vv = +q.split('/').pop();
// @ts-ignore 111
vertices[(i * k.length + j) * 3 + 2] = vv;
}
}
planMesh.geometry.computeVertexNormals();
console.log(heightData, terrainWidthExtents, terrainDepthExtents, terrainWidth, terrainDepth)
console.log(terrainMaxX, terrainMinX)
// This parameter is not really used, since we are using PHY_FLOAT height data type and hence it is ignored
var heightScale = 1;
// Up axis = 0 for X, 1 for Y, 2 for Z. Normally 1 = Y is used.
var upAxis = 1;
// hdt, height data type. "PHY_FLOAT" is used. Possible values are "PHY_FLOAT", "PHY_UCHAR", "PHY_SHORT"
var hdt = "PHY_FLOAT"
// "PHY_FLOAT";
// Set this to your needs (inverts the triangles)
var flipQuadEdges = false;
// Creates height data buffer in Ammo heap
const ammoHeightData = Ammo._malloc( 4 * terrainWidth * terrainDepth );
console.log('ammoHeightData:', ammoHeightData)
// Copy the javascript height data array to the Ammo one.
var p = 0;
var p2 = 0;
for ( var j = 0; j < terrainDepthOfKeys.length; j ++ ) {
for ( var i = 0; i < terrainWidthOfKeys.length; i ++ ) {
const t = heightData[terrainDepthOfKeys[j]][terrainWidthOfKeys[i]] || '0/0/0'
// write 32-bit float data to memory
Ammo.HEAPF32[ammoHeightData + p2 >> 2] = +t.split('/').pop();
p ++;
// 4 bytes/float
p2 += 4;
}
}
// Creates the heightfield physics shape
var heightFieldShape = new Ammo.btHeightfieldTerrainShape(
terrainWidth,
terrainDepth,
ammoHeightData,
heightScale,
terrainMinHeight,
terrainMaxHeight,
upAxis,
// @ts-expect-error
hdt,
flipQuadEdges
);
// Set horizontal scale
var scaleX = terrainWidthExtents / ( terrainWidth - 1 );
var scaleZ = terrainDepthExtents / ( terrainDepth - 1 );
heightFieldShape.setLocalScaling( new Ammo.btVector3( scaleX, 1, scaleZ ) );
heightFieldShape.setMargin( 0.05 );
var groundTransform = new Ammo.btTransform();
groundTransform.setIdentity();
// Shifts the terrain, since bullet re-centers it on its bounding box.
groundTransform.setOrigin( new Ammo.btVector3( 0, ( terrainMaxHeight + terrainMinHeight ) / 2, 0 ) );
var groundMass = 0;
var groundLocalInertia = new Ammo.btVector3( 0, 0, 0 );
var groundMotionState = new Ammo.btDefaultMotionState( groundTransform );
var groundBody = new Ammo.btRigidBody( new Ammo.btRigidBodyConstructionInfo( groundMass, groundMotionState, heightFieldShape, groundLocalInertia ) );
return [groundBody, planMesh]
}
\ No newline at end of file
import { KeyBoardStateStore } from './../module/keyboardState/keyboardState'; import { KeyBoardStateStore } from './../module/keyboardState/keyboardState';
import * as THREE from "three"; import * as THREE from "three";
import { EventDispatcher } from "../module/EventDispatcher"; import { EventDispatcher } from "../module/EventDispatcher";
import { GLTFLoader } from '../module/loaders/GLTFLoader';
const materialDynamic = new THREE.MeshPhongMaterial( { color:0xfca400 } ); const materialDynamic = new THREE.MeshPhongMaterial( { color:0xfca400 } );
const materialStatic = new THREE.MeshPhongMaterial( { color:0x999999 } ); const materialStatic = new THREE.MeshPhongMaterial( { color:0x999999 } );
...@@ -42,23 +43,32 @@ function createElement(type: string, className: string, style: Partial<CSSStyleD ...@@ -42,23 +43,32 @@ function createElement(type: string, className: string, style: Partial<CSSStyleD
type ActionNameEnum = 'acceleration' | 'braking' | 'left' | 'right'; type ActionNameEnum = 'acceleration' | 'braking' | 'left' | 'right';
const GLTFLoaderIns = new GLTFLoader()
interface GltfModel {
animations: THREE.AnimationClip[],
scene: THREE.Scene,
}
export class Vehicle extends THREE.Object3D{ export class Vehicle extends THREE.Object3D{
chassisMesh: THREE.Mesh // 车身 chassisMesh: THREE.Group // 车身
fixedChassicMesh: THREE.Mesh // 固定的车身 fixedChassicMesh: THREE.Group // 固定的车身
wheelMeshes: any[] = [] wheelMeshes: any[] = []
chassisRidigBody: Ammo.btRigidBody chassisRidigBody: Ammo.btRigidBody
raycastVehicle: Ammo.btRaycastVehicle raycastVehicle: Ammo.btRaycastVehicle
btVehicleTuning: Ammo.btVehicleTuning btVehicleTuning: Ammo.btVehicleTuning
sppedBoard: HTMLElement // 速度面板 sppedBoard: HTMLElement // 速度面板
luntaiIns: GltfModel // 轮胎模型
constructor(pos: THREE.Vector3, quat: THREE.Quaternion) { constructor(pos: THREE.Vector3, quat: THREE.Quaternion) {
super() super()
// this.initChassisMesh() // this.initChassisMesh()
this.createVehicle(pos, quat) this.createVehicle(pos, quat)
this.addEventListener('update', this.update) // this.addEventListener('update', this.update)
} }
initChassisMesh() { initChassisMesh() {
...@@ -89,12 +99,23 @@ export class Vehicle extends THREE.Object3D{ ...@@ -89,12 +99,23 @@ export class Vehicle extends THREE.Object3D{
body.setActivationState(4); body.setActivationState(4);
var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength); var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength);
GLTFLoaderIns.load('qiche.gltf', (gltf: GltfModel) => {
chassisMesh.add(gltf.scene)
gltf.scene.translateY(-0.6)
gltf.scene.traverse(function(obj) {
// @ts-ignore
if (obj.isMesh) {
obj.castShadow = true
}
})
})
// this.fixedChassicMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength) // this.fixedChassicMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength)
this.fixedChassicMesh = this.chassisMesh.add(new THREE.Mesh( // this.fixedChassicMesh = this.chassisMesh.add(new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1), // new THREE.BoxGeometry(1, 1, 1),
materialDynamic // materialDynamic
)) // ))
this.sppedBoard = createElement('div', 'speedboard', { this.sppedBoard = createElement('div', 'speedboard', {
position: 'fixed', position: 'fixed',
...@@ -234,6 +255,14 @@ export class Vehicle extends THREE.Object3D{ ...@@ -234,6 +255,14 @@ export class Vehicle extends THREE.Object3D{
} }
/**
* 添加轮子
* @param isFront 是否是前轮
* @param pos 坐标
* @param radius 半径
* @param width 宽度
* @param index 索引值
*/
addWheel(isFront: boolean, pos: Ammo.btVector3, radius: number, width: number, index: number) { addWheel(isFront: boolean, pos: Ammo.btVector3, radius: number, width: number, index: number) {
const vehicle = this.raycastVehicle const vehicle = this.raycastVehicle
const tuning = this.btVehicleTuning const tuning = this.btVehicleTuning
...@@ -269,24 +298,38 @@ export class Vehicle extends THREE.Object3D{ ...@@ -269,24 +298,38 @@ export class Vehicle extends THREE.Object3D{
} }
createWheelMesh(radius: number, width: number) { createWheelMesh(radius: number, width: number) {
const group = new THREE.Group()
var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1); var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
t.rotateZ(Math.PI / 2); t.rotateZ(Math.PI / 2);
var mesh = new THREE.Mesh(t, materialInteractive); var mesh = new THREE.Mesh(t, materialInteractive);
mesh.add(new THREE.Mesh(new THREE.BoxGeometry(width * 1.5, radius * 1.75, radius*.25, 1, 1, 1), materialInteractive)); mesh.add(new THREE.Mesh(new THREE.BoxGeometry(width * 1.5, radius * 1.75, radius*.25, 1, 1, 1), materialInteractive));
mesh.castShadow = true mesh.castShadow = true
this.add(mesh); group.add(mesh);
return mesh; mesh.visible = false
const luntai = this.luntaiIns.scene.clone()
luntai.traverse(function(obj) {
// @ts-ignore
if (obj.isMesh) {
obj.castShadow = true
}
})
group.add(luntai)
this.add(group)
return group;
} }
createChassisMesh(w: number, l: number, h: number) { createChassisMesh(w: number, l: number, h: number) {
const group = new THREE.Group()
var shape = new THREE.BoxGeometry(w, l, h, 1, 1, 1); var shape = new THREE.BoxGeometry(w, l, h, 1, 1, 1);
var mesh = new THREE.Mesh(shape, materialInteractive); var mesh = new THREE.Mesh(shape, materialInteractive);
mesh.castShadow = true mesh.castShadow = true
this.add(mesh); mesh.visible = false
return mesh; group.add(mesh);
this.add(group)
return group;
} }
initPhysics(physicsWorld: Ammo.btDiscreteDynamicsWorld) { async initPhysics(physicsWorld: Ammo.btDiscreteDynamicsWorld) {
physicsWorld.addRigidBody(this.chassisRidigBody) physicsWorld.addRigidBody(this.chassisRidigBody)
...@@ -297,17 +340,24 @@ export class Vehicle extends THREE.Object3D{ ...@@ -297,17 +340,24 @@ export class Vehicle extends THREE.Object3D{
vehicle.setCoordinateSystem(0, 1, 2); // 设置坐标系? vehicle.setCoordinateSystem(0, 1, 2); // 设置坐标系?
physicsWorld.addAction(vehicle); // addAction physicsWorld.addAction(vehicle); // addAction
var wheelAxisPositionBack = -1; var wheelAxisPositionBack = -1.3;
var wheelRadiusBack = .4; var wheelRadiusBack = .4;
var wheelWidthBack = .3; var wheelWidthBack = .3;
var wheelHalfTrackBack = 1; var wheelHalfTrackBack = 0.8;
var wheelAxisHeightBack = .3; var wheelAxisHeightBack = .3;
var wheelAxisFrontPosition = 1.7; var wheelAxisFrontPosition = 1.5;
var wheelHalfTrackFront = 1; var wheelHalfTrackFront = 0.8;
var wheelAxisHeightFront = .3; var wheelAxisHeightFront = .3;
var wheelRadiusFront = .35; var wheelRadiusFront = .35;
var wheelWidthFront = 0.2; var wheelWidthFront = 0.2;
const LuntaiIns = this.luntaiIns = await new Promise<GltfModel>(resolve => {
GLTFLoaderIns.load('luntai.gltf', (ins: GltfModel) => {
resolve(ins)
})
})
this.addWheel(true, new Ammo.btVector3(wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_LEFT); this.addWheel(true, new Ammo.btVector3(wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_LEFT);
this.addWheel(true, new Ammo.btVector3(-wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_RIGHT); this.addWheel(true, new Ammo.btVector3(-wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition), wheelRadiusFront, wheelWidthFront, FRONT_RIGHT);
this.addWheel(false, new Ammo.btVector3(-wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack), wheelRadiusBack, wheelWidthBack, BACK_LEFT); this.addWheel(false, new Ammo.btVector3(-wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack), wheelRadiusBack, wheelWidthBack, BACK_LEFT);
......
import { CarScene } from "./CarScene" import { CarScene } from "./CarScene"
import * as THREE from 'three'
window['THREE'] = THREE
export class StageScene { export class StageScene {
constructor() { constructor() {
......
...@@ -20,8 +20,11 @@ export class AmmoPhysicWorld { ...@@ -20,8 +20,11 @@ export class AmmoPhysicWorld {
DISABLE_DEACTIVATION: number = 4 DISABLE_DEACTIVATION: number = 4
TRANSFORM_AUX: Ammo.btTransform = new Ammo.btTransform(); TRANSFORM_AUX: Ammo.btTransform = new Ammo.btTransform();
ZERO_QUATERNION: THREE.Quaternion = new THREE.Quaternion(0, 0, 0, 1); ZERO_QUATERNION: THREE.Quaternion = new THREE.Quaternion(0, 0, 0, 1);
DEFAULTVECTOR3: THREE.Vector3 = new THREE.Vector3()
DEFAULT_MATRIX3: THREE.Matrix3 = new THREE.Matrix3()
dynamicBodyList: DynamicBody[] = [] dynamicBodyList: DynamicBody[] = []
rigidBodyList: Ammo.btRigidBody[] = []
constructor() { constructor() {
this.clock = new THREE.Clock(); this.clock = new THREE.Clock();
...@@ -42,7 +45,7 @@ export class AmmoPhysicWorld { ...@@ -42,7 +45,7 @@ export class AmmoPhysicWorld {
} }
createMeshPhysicBody(mesh: THREE.Mesh, cfg: Partial<BodyConfig> = {}) { createMeshPhysicBody(mesh: THREE.Mesh, cfg: Partial<BodyConfig> = {}) {
console.log(mesh.type, mesh, mesh.geometry) // console.log(mesh.type, mesh, mesh.geometry)
// @ts-expect-error // @ts-expect-error
const parameters = mesh.geometry.parameters; const parameters = mesh.geometry.parameters;
const geometry = mesh.geometry; const geometry = mesh.geometry;
...@@ -110,6 +113,11 @@ export class AmmoPhysicWorld { ...@@ -110,6 +113,11 @@ export class AmmoPhysicWorld {
return ridigBody return ridigBody
} }
addRigidBodyWithMeshObj(body: Ammo.btRigidBody) {
this.physicWorld.addRigidBody(body)
this.rigidBodyList.push(body)
}
addDynamicBody(body: DynamicBody) { addDynamicBody(body: DynamicBody) {
body.initPhysics(this.physicWorld) body.initPhysics(this.physicWorld)
this.dynamicBodyList.push(body) this.dynamicBodyList.push(body)
...@@ -122,6 +130,25 @@ export class AmmoPhysicWorld { ...@@ -122,6 +130,25 @@ export class AmmoPhysicWorld {
syncList[i](dt) syncList[i](dt)
} }
for (let i = 0, rigidBodyList = this.rigidBodyList; i < rigidBodyList.length; i++) {
const currBody = rigidBodyList[i]
if (currBody.meshData && currBody.meshData.isMesh) {
const motionStateIns = currBody.getMotionState()
if (motionStateIns) {
motionStateIns.getWorldTransform(this.TRANSFORM_AUX)
const p = this.TRANSFORM_AUX.getOrigin()
const q = this.TRANSFORM_AUX.getRotation()
this.DEFAULTVECTOR3.set(p.x(), p.y(), p.z())
this.DEFAULT_MATRIX3.setFromMatrix4((currBody.meshData as THREE.Mesh).matrixWorld)
this.DEFAULTVECTOR3.applyMatrix3(this.DEFAULT_MATRIX3.invert())
currBody.meshData.position.set(
this.DEFAULTVECTOR3.x, this.DEFAULTVECTOR3.y, this.DEFAULTVECTOR3.z
)
currBody.meshData.quaternion.set(q.x(), q.y(), q.z(), q.w());
}
}
}
const meshes = this.meshes const meshes = this.meshes
for ( let i = 0, l = meshes.length; i < l; i ++ ) { for ( let i = 0, l = meshes.length; i < l; i ++ ) {
const mesh = meshes[i]; const mesh = meshes[i];
......
This diff is collapsed.
...@@ -483,6 +483,7 @@ declare namespace Ammo { ...@@ -483,6 +483,7 @@ declare namespace Ammo {
set_m_additionalAngularDampingFactor(m_additionalAngularDampingFactor: number): void; set_m_additionalAngularDampingFactor(m_additionalAngularDampingFactor: number): void;
} }
class btRigidBody extends btCollisionObject { class btRigidBody extends btCollisionObject {
meshData: any;
constructor(constructionInfo: btRigidBodyConstructionInfo); constructor(constructionInfo: btRigidBodyConstructionInfo);
getCenterOfMassTransform(): btTransform; getCenterOfMassTransform(): btTransform;
setCenterOfMassTransform(xform: btTransform): void; setCenterOfMassTransform(xform: btTransform): void;
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": [ "lib": [
"DOM", "DOM",
"ES2015", "ES2020",
"ES5"
], ],
"sourceMap": true, "sourceMap": true,
"noEmitOnError": true, "noEmitOnError": true,
......
Arguments: Arguments:
/usr/local/bin/node /usr/local/bin/yarn add ammonjs /usr/local/bin/node /usr/local/bin/yarn add 0.54.0
PATH: PATH:
/usr/local/bin:/usr/local/sbin:/Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin:/Library/Frameworks/Python.framework/Versions/3.9/bin /usr/local/bin:/usr/local/sbin:/Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin:/Library/Frameworks/Python.framework/Versions/3.9/bin
...@@ -14,12 +14,17 @@ Platform: ...@@ -14,12 +14,17 @@ Platform:
darwin x64 darwin x64
Trace: Trace:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: registry.npm.org. is not in the cert's altnames: DNS:*.cloudwaysapps.com, DNS:cloudwaysapps.com Error: http://npm.dui88.com/0.54.0: no such package available
at Object.checkServerIdentity (tls.js:297:12) at Request.params.callback [as _callback] (/usr/local/lib/node_modules/yarn/lib/cli.js:66988:18)
at TLSSocket.onConnectSecure (_tls_wrap.js:1507:27) at Request.self.callback (/usr/local/lib/node_modules/yarn/lib/cli.js:140662:22)
at TLSSocket.emit (events.js:315:20) at Request.emit (events.js:315:20)
at TLSSocket._finishInit (_tls_wrap.js:932:8) at Request.<anonymous> (/usr/local/lib/node_modules/yarn/lib/cli.js:141634:10)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:706:12) at Request.emit (events.js:315:20)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/yarn/lib/cli.js:141556:12)
at Object.onceWrapper (events.js:421:28)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
npm manifest: npm manifest:
{ {
...@@ -40,7 +45,7 @@ npm manifest: ...@@ -40,7 +45,7 @@ npm manifest:
"dependencies": { "dependencies": {
"@types/three": "^0.143.0", "@types/three": "^0.143.0",
"oimo": "^1.0.9", "oimo": "^1.0.9",
"three": "^0.143.0", "three": "0.66.75",
"ts-loader": "^9.3.1", "ts-loader": "^9.3.1",
"typescript": "^4.7.4", "typescript": "^4.7.4",
"webpack": "^5.74.0", "webpack": "^5.74.0",
...@@ -1944,10 +1949,10 @@ Lockfile: ...@@ -1944,10 +1949,10 @@ Lockfile:
commander "^2.20.0" commander "^2.20.0"
source-map-support "~0.5.20" source-map-support "~0.5.20"
three@^0.143.0: three@0.66.75:
version "0.143.0" version "0.66.75"
resolved "http://npm.dui88.com:80/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df" resolved "http://npm.dui88.com:80/three/-/three-0.66.75.tgz#45bc2017a52bf616ab822ecd3f54393c946c6825"
integrity sha512-oKcAGYHhJ46TGEuHjodo2n6TY2R6lbvrkp+feKZxqsUL/WkH7GKKaeu6RHeyb2Xjfk2dPLRKLsOP0KM2VgT8Zg== integrity sha1-RbwgF6Ur9hargi7NP1Q5PJRsaCU=
thunky@^1.0.2: thunky@^1.0.2:
version "1.1.0" version "1.1.0"
......
...@@ -186,10 +186,10 @@ ...@@ -186,10 +186,10 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/three@^0.143.0": "@types/three@^0.144.0":
version "0.143.0" version "0.144.0"
resolved "http://npm.dui88.com:80/@types%2fthree/-/three-0.143.0.tgz#686f1221c4c89d797713f0533d2f129afcc3572d" resolved "http://npm.dui88.com:80/@types%2fthree/-/three-0.144.0.tgz#a154f40122dbc3668c5424a5373f3965c6564557"
integrity sha512-c5PonXOt8xk5q4ygmyjOX4Ec+FA7gwfdcMT/PveE9xrJs/0DDcf2lJkWrhEcmvx2ZefQCQBcogABnGqB0P4OsA== integrity sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==
dependencies: dependencies:
"@types/webxr" "*" "@types/webxr" "*"
...@@ -1889,10 +1889,10 @@ terser@^5.7.2: ...@@ -1889,10 +1889,10 @@ terser@^5.7.2:
commander "^2.20.0" commander "^2.20.0"
source-map-support "~0.5.20" source-map-support "~0.5.20"
three@^0.143.0: three@^0.144.0:
version "0.143.0" version "0.144.0"
resolved "http://npm.dui88.com:80/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df" resolved "http://npm.dui88.com:80/three/-/three-0.144.0.tgz#2818517169f8ff94eea5f664f6ff1fcdcd436cc8"
integrity sha512-oKcAGYHhJ46TGEuHjodo2n6TY2R6lbvrkp+feKZxqsUL/WkH7GKKaeu6RHeyb2Xjfk2dPLRKLsOP0KM2VgT8Zg== integrity sha512-R8AXPuqfjfRJKkYoTQcTK7A6i3AdO9++2n8ubya/GTU+fEHhYKu1ZooRSCPkx69jbnzT7dD/xEo6eROQTt2lJw==
thunky@^1.0.2: thunky@^1.0.2:
version "1.1.0" version "1.1.0"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment