gpt4 book ai didi

javascript - 曲线上的 Three.js getTangent 应该在曲线上移动时正确旋转我的对象

转载 作者:行者123 更新时间:2023-11-30 21:01:56 26 4
gpt4 key购买 nike

它确实会旋转,使用:

t = 0
animate = ->
requestAnimationFrame animate

t += 0.001
# ...

position3 = curveSeaRoute.getPoint(t+.3)
tangent3 = curveSeaRoute.getTangent(t)
ship.position.copy(position3)
ship.lookAt(tangent3)
# console.log tangent3

renderer.render scene, camera
animate()

我的 ship + 'route' 定义如下:

# Ship
centerLength = 2
bodyLength = 3
bodyWidth = 2
deckHeight = 0.1
geometry = new THREE.Geometry()
v1 = new THREE.Vector3(1, deckHeight,0)
v2 = new THREE.Vector3(-2, deckHeight,2)
v3 = new THREE.Vector3(1, deckHeight,2)
v4 = new THREE.Vector3(-2, deckHeight,0)
v5 = new THREE.Vector3(-3, deckHeight, 1)
geometry.vertices.push(v1)
geometry.vertices.push(v2)
geometry.vertices.push(v3)
geometry.vertices.push(v4)
geometry.vertices.push(v5)
geometry.faces.push( new THREE.Face3( 0, 1, 2 ) )
geometry.faces.push( new THREE.Face3( 3, 1, 0 ) )
geometry.faces.push( new THREE.Face3( 3, 4, 1 ) )
material = new THREE.MeshBasicMaterial( { color: 0x005b1e } )
ship = new THREE.Mesh( geometry, material )
ship.translateZ 20
ship.translateX 14.5
scene.add( ship )

# Sea route
curveSeaRoute = new THREE.CatmullRomCurve3([
new THREE.Vector3( 18, roadHeight, 31 ),
new THREE.Vector3( 24, roadHeight, 23 ),
new THREE.Vector3( 22, roadHeight, 20 ),
new THREE.Vector3( 14, roadHeight, 19 ),
new THREE.Vector3( 10, roadHeight, 20 ),
new THREE.Vector3( 8, roadHeight, 23 ),
new THREE.Vector3( 10, roadHeight, 31 ),
] )

geometry = new THREE.Geometry()
geometry.vertices = curveSeaRoute.getPoints( 200 )
material = new THREE.LineBasicMaterial( { color : 0x45607c } )
curveObject = new THREE.Line( geometry, material )
scene.add( curveObject )

但旋转不是很好的问题:

http://jsfiddle.net/CoderX99/66b3j9wa/6/

getTangent 确实为我提供了关于曲线方向矢量(切线)的宝贵数据。现在我当然可以使用三 Angular 学从 x 和 z 值中获取 y 轴旋转 Angular ,但我希望有更简单的方法 - Three.js - 方法。

此外,我希望旋转中心位于船的中间。看起来它现在就在后面的某个地方。

回答

来自 prisoner849。加上整理我自己的代码。

setOutPath = (path, color, segments ) ->
geometry = new THREE.Geometry()
geometry.vertices = path.getPoints( segments )
material = new THREE.LineBasicMaterial( { color : color } )
curveObject = new THREE.Line( geometry, material )
scene.add( curveObject )

setOutPath(curveRoadNo1, 0xa9c41e, 500)
setOutPath(curveRoadNo2, 0xa9c41e, 200)
setOutPath(curveSeaRoute, 0x45607c, 200)

# Moving objects
# Vehicle
geometry = new THREE.SphereBufferGeometry( 0.1, 32, 32 )
material = new THREE.MeshBasicMaterial( {color: 0xffff00} )
vehicle1 = new THREE.Mesh( geometry, material )
scene.add( vehicle1 )
vehicle2 = vehicle1.clone()
scene.add( vehicle2 )
vehicle3 = vehicle1.clone()
scene.add( vehicle3 )
# The ship
centerLength = 2
bodyLength = 3
bodyWidth = 2
deckHeight = 0.1
geometry = new THREE.PlaneGeometry(2,2,2)
geometry.vertices[4].y = -3
geometry.rotateX(-Math.PI * 0.5)
geometry.translate(0, deckHeight, 0)
material = new THREE.MeshBasicMaterial({
color: 0x005b1e
})
ship = new THREE.Mesh(geometry, material)
ship.translateZ(15)
ship.translateX(15)
scene.add(ship)
# vehicle1, vehicle2, vehicle3, ship

t1 = { value: 0 } # for RoadNo1
t2 = { value: 0 } # for RoadNo2
t3 = { value: 0 } # for SeaRoute

# Tween updates
updateT = ->
vehicle1.position.copy(curveRoadNo1.getPointAt(t1.value))
vehicle2.position.copy(curveRoadNo1.getPointAt(1 - t1.value))
updateT2 = ->
vehicle3.position.copy(curveRoadNo2.getPointAt(t2.value))
updateT3 = ->
lookAt = (t3.value + 0.0001) % 1
ship.position.copy(curveSeaRoute.getPointAt(t3.value))
ship.lookAt(curveSeaRoute.getPointAt(lookAt))

# Tweens - for Inbetweens
tween11 = new TWEEN.Tween(t1).to({ value: .3 }, 7000).delay(500).onUpdate(updateT)
tween12 = new TWEEN.Tween(t1).to({ value: 1 }, 3000).delay(1000).onUpdate(updateT).onComplete( () ->
t1.value = 0
)
tween11.chain(tween12)
tween12.chain(tween11)
tween11.start()

tween21 = new TWEEN.Tween(t2).to({ value: 1 }, 10000).onUpdate(updateT2)
tween22 = new TWEEN.Tween(t2).to({ value: 0 }, 10000).onUpdate(updateT2)
tween21.chain(tween22)
tween22.chain(tween21)
tween21.start()

tween3 = new TWEEN.Tween(t3).to({ value: 1 }, 17000).delay(1500).onUpdate(updateT3).onComplete( () ->
t3.value = 0
)
tween3.chain(tween3)
tween3.start()

controls = new THREE.OrbitControls(camera, renderer.domElement)
camera.position.x = colms/2
camera.position.y = 13
camera.position.z = 25
camera.rotation.x = -40 * Math.PI / 180
controls.target = new THREE.Box3().setFromObject(scene).getCenter()
controls.update()

t = 0
animate = ->
requestAnimationFrame animate
TWEEN.update()
renderer.render scene, camera
animate()

最佳答案

您可以使用ship.lookAt() 方法。看一下 updateT3 函数。

我修改了你的 jsfiddle(稍微):简化了飞船的创建;使用 Tween.js 制作动画;添加了 THREE.OrbitControls() 以获得更好的 View 。

查看代码片段。

// Generated by CoffeeScript 2.0.1
(function() {
var animate, bodyLength, bodyWidth, build_city, camera, centerLength, city_map, colms, curveObject, curveRoadNo1, curveRoadNo2, deckHeight, flora_density_map, geometry, height, heightBuilding, height_map, i, j, k, len, len1, material, plant_tree, raise_land, ref, renderer, roadHeight, rows, scene, ship, t, v1, v2, v3, v4, v5, vehicle;

scene = new THREE.Scene;

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);

renderer = new THREE.WebGLRenderer({
antialias: true
});

renderer.setSize(window.innerWidth, window.innerHeight);

renderer.setPixelRatio((ref = window.devicePixelRatio) != null ? ref : window.devicePixelRatio || 1);

document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

//##########################################################################################
colms = 30;

rows = 14;

height_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 4, 5, 5, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 2, 1, 3, 4, 7, 5, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 2, 3, 3, 4, 5, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 4, 5, 6, 6];

flora_density_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0];

city_map = [9, 9, 9, 9, 9, 0, 0, 9, 9, 0, 0, 9];

plant_tree = function(x, y, z) {
var cone, geometry, material;
geometry = new THREE.ConeGeometry(0.2, 0.5);
material = new THREE.MeshBasicMaterial({
color: 0x20281e
});
cone = new THREE.Mesh(geometry, material);
cone.translateX(x);
cone.translateY(y + .25);
cone.translateZ(z);
return scene.add(cone);
};

build_city = function(start_c, start_r, colms, rows, i, heightBuilding) {
var geometry, height, land, material, row, width;
if (heightBuilding !== 0) {
height = heightBuilding * 0.035;
width = 0.5;
geometry = new THREE.BoxGeometry(width, height, width);
material = new THREE.MeshBasicMaterial({
color: 0x8b0000
});
land = new THREE.Mesh(geometry, material);
// Set box base equal to overall baselevel.
land.translateY(height / 2);
// Normal animation translation.
row = (Math.floor(i / colms)) + 1;
land.translateZ(row + start_r - 1);
land.translateX(i - (colms * (row - 1)) + start_c);
return scene.add(land);
}
};

raise_land = function(colms, rows, i, height) {
var color, geometry, land, material, row;
color = new THREE.Color(`rgb(${0 + height * 12}, 153, ${51 + height * 30})`);
height = height * 0.22;
geometry = new THREE.BoxGeometry(1, height, 1);
material = new THREE.MeshBasicMaterial({
color: color
});
land = new THREE.Mesh(geometry, material);
// Set box base equal to overall baselevel.
land.translateY(height / 2);
// Normal animation translation.
row = (Math.floor(i / colms)) + 1;
land.translateZ(row);
land.translateX(i - (colms * (row - 1)));
scene.add(land);
if (flora_density_map[i] !== 0) {
return plant_tree(i - (colms * (row - 1)), height, row);
}
};

centerLength = 2;

bodyLength = 3;

bodyWidth = 2;

deckHeight = 0.1;

geometry = new THREE.PlaneGeometry(2, 2, 2);
geometry.vertices[4].y = -3;
geometry.rotateX(-Math.PI * .5);
geometry.translate(0, .1, 0);
material = new THREE.MeshBasicMaterial({
color: 0x005b1e
});

ship = new THREE.Mesh(geometry, material);

ship.translateZ(15);

ship.translateX(15);

scene.add(ship);

// Roads around the main settlement.
roadHeight = 0.1;

curveRoadNo1 = new THREE.CatmullRomCurve3([
new THREE.Vector3(13,
roadHeight,
13),
new THREE.Vector3(12,
roadHeight,
14),
new THREE.Vector3(10,
roadHeight,
14),
new THREE.Vector3(10,
roadHeight,
13),
new THREE.Vector3(11,
roadHeight,
12),
new THREE.Vector3(11,
roadHeight,
11),
// new THREE.Vector3( 9, roadHeight, 10),
// new THREE.Vector3( 7, roadHeight, 9),
new THREE.Vector3(4,
roadHeight,
10),
new THREE.Vector3(4,
roadHeight,
7),
new THREE.Vector3(1,
roadHeight,
3),
new THREE.Vector3(5,
roadHeight,
2),
new THREE.Vector3(10,
roadHeight,
4),
new THREE.Vector3(15,
roadHeight,
3),
new THREE.Vector3(18,
roadHeight,
6),
new THREE.Vector3(22,
roadHeight,
2),
new THREE.Vector3(25,
roadHeight,
5),
new THREE.Vector3(25,
roadHeight,
7),
new THREE.Vector3(21,
roadHeight,
11),
new THREE.Vector3(19,
roadHeight,
9),
new THREE.Vector3(17,
roadHeight,
11),
new THREE.Vector3(19,
roadHeight,
12),
new THREE.Vector3(18,
roadHeight,
13)
]);

curveRoadNo2 = new THREE.CatmullRomCurve3([new THREE.Vector3(15, roadHeight, 11), new THREE.Vector3(12, roadHeight, 12), new THREE.Vector3(11, roadHeight, 11), new THREE.Vector3(11, roadHeight, 9), new THREE.Vector3(12, roadHeight, 8), new THREE.Vector3(12, roadHeight, 5), new THREE.Vector3(15, roadHeight, 3), new THREE.Vector3(17, roadHeight, 7), new THREE.Vector3(16, roadHeight, 8), new THREE.Vector3(16, roadHeight, 9), new THREE.Vector3(17, roadHeight, 11)]);

curveRoadNo2.closed = true;

geometry = new THREE.Geometry();

geometry.vertices = curveRoadNo1.getPoints(300);

material = new THREE.LineBasicMaterial({
color: 0xa9c41e
});

curveObject = new THREE.Line(geometry, material);

scene.add(curveObject);

geometry = new THREE.Geometry();

geometry.vertices = curveRoadNo2.getPoints(200);

material = new THREE.LineBasicMaterial({
color: 0xa9c41e
});

curveObject = new THREE.Line(geometry, material);

scene.add(curveObject);

geometry = new THREE.SphereBufferGeometry(0.2, 32, 32);

material = new THREE.MeshBasicMaterial({
color: 0xffff00
});

vehicle = new THREE.Mesh(geometry, material);

scene.add(vehicle);

for (i = j = 0, len = height_map.length; j < len; i = ++j) {
height = height_map[i];
// vehicle.position.x = 15
// vehicle.position.z = 3

// Fundaments of scene.
raise_land(30, 14, i, height);
}

for (i = k = 0, len1 = city_map.length; k < len1; i = ++k) {
heightBuilding = city_map[i];
build_city(14, 12, 4, 3, i, heightBuilding);
}

camera.position.x = colms / 2;

camera.position.y = 15;

camera.position.z = 30;

controls.target = new THREE.Box3().setFromObject(scene).getCenter();
controls.update();

t = {
value: 0
};

vehicle2 = new THREE.Mesh(vehicle.geometry, vehicle.material);
scene.add(vehicle2);

vehicle3 = new THREE.Mesh(vehicle.geometry, vehicle.material);
scene.add(vehicle3);

var tween11 = new TWEEN.Tween(t).to({
value: .3
}, 7000).delay(500).onUpdate(updateT);
var tween12 = new TWEEN.Tween(t).to({
value: 1
}, 3000).delay(1000).onUpdate(updateT).onComplete(function() {
t.value = 0
});
tween11.chain(tween12);
tween12.chain(tween11);
tween11.start();

function updateT() {
vehicle.position.copy(curveRoadNo2.getPointAt(t.value));
vehicle2.position.copy(curveRoadNo2.getPointAt(1 - t.value));
}

let t2 = {
value: 0
};
var tween21 = new TWEEN.Tween(t2).to({
value: 1
}, 10000).onUpdate(updateT2);
var tween22 = new TWEEN.Tween(t2).to({
value: 0
}, 10000).onUpdate(updateT2);
tween21.chain(tween22);
tween22.chain(tween21);
tween21.start();

function updateT2() {
vehicle3.position.copy(curveRoadNo1.getPointAt(t2.value));
}

var shipCurve = new THREE.CatmullRomCurve3([
new THREE.Vector3(15, 0, 15),
new THREE.Vector3(0, 0, 25),
new THREE.Vector3(30, 0, 25)
]);
shipCurve.closed = true;

var shipLineGeometry = new THREE.Geometry();
shipLineGeometry.vertices = shipCurve.getPoints(200);
var shipLine = new THREE.Line(shipLineGeometry, new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(shipLine);

let t3 = {
value: 0
};
var tween3 = new TWEEN.Tween(t3).to({
value: 1
}, 17000).delay(1500).onUpdate(updateT3).onComplete(function() {
t3.value = 0;
});
tween3.chain(tween3);
tween3.start();

function updateT3() {
let lookAt = (t3.value + 0.0001) % 1;
ship.position.copy(shipCurve.getPointAt(t3.value));
ship.lookAt(shipCurve.getPointAt(lookAt));
}

animate = function() {
requestAnimationFrame(animate);
TWEEN.update();
renderer.render(scene, camera);
};

animate();

}).call(this);
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/tween.min.js"></script>

作为引用,看看这个example的源代码.

关于javascript - 曲线上的 Three.js getTangent 应该在曲线上移动时正确旋转我的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47052391/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com