我不太懂html/javascript,我从three.js开始。我做了一个场景,它依赖于一个可以由用户控制的参数。
下面的代码是这样一个场景的完整的最小示例。它呈现一个参数曲面,它依赖于用户可以用a更改的参数input type="number"。
显然,这不是一个好的方式进行:场景是动画和动画加速时,一个播放参数,我不知道为什么。对这样一个场景进行编码的好方法是什么?
<html>
<head>
<title>Dupin cyclide</title>
<style>
canvas {
width: 100%;
height: 100%
}
</style>
</head>
<body>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="a">a: </label>
<input id="a" type="number" step="0.1" min="0.5" value="0.9"/>
<script> // change event -----------------------------------------------------
$("#a").on("change", function(){
Rendering(this.value);
})
</script>
<script> // cyclide parametrization ------------------------------------------
function fcyclide(a, c, mu) {
var b = Math.sqrt(a * a - c * c);
return function (u, v, vector) {
var uu = 2 * u * Math.PI; var vv = 2 * v * Math.PI;
var cosu = Math.cos(uu); var cosv = Math.cos(vv);
var h = a - c * cosu * cosv;
var x = (mu * (c - a * cosu * cosv) + b * b * cosu) / h;
var y = (b * Math.sin(uu) * (a - mu * cosv)) / h;
var z = b * Math.sin(vv) * (c * cosu - mu) / h;
vector.x = x; vector.y = y; vector.z = z;
}
}
</script>
<script> // add cyclide to object --------------------------------------------
function addCyclide(object, a) {
var geom = new THREE.ParametricGeometry(
fcyclide(a, 0.34, 0.56), 40, 40);
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh(geom, material);
object.add(mesh);
}
</script>
<script> // three.js ---------------------------------------------------------
var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(70, aspect, 1, 10000);
camera.position.z = 4;
scene.add(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var object = new THREE.Object3D()
scene.add(object);
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function render() {
renderer.render(scene, camera);
object.rotation.x += 0.001; object.rotation.y += 0.001;
requestAnimFrame(render);
}
</script>
<script> // Rendering function -----------------------------------------------
function Rendering(a) {
object.children.splice(0); // clear scene
addCyclide(object, a);
render();
}
</script>
<script> // Render the scene -------------------------------------------------
Rendering(0.9);
</script>
</body>
</html> 发布于 2018-07-01 10:40:54
显然,这不是一个好的方式进行:场景是动画和动画加速时,一个播放参数,我不知道为什么。
每次调用requestAnimFrame时,setTimeout都会启动计时器。计时器调用render,后者再次启动定时器并重复该进程。初始化由render调用的函数Rendering(a)。
但是,由于Rendering(a)也是由change事件调用的,所以每次更改输入时都会启动一个新的计时器。更改输入的频率越高,同时运行的计时器就越多。这会导致加速。
要解决这个问题,必须从render中删除Rendering(a)调用。
function Rendering(a)
{
object.children.splice(0);
addCyclide(object, a);
}但是在启动时给requestAnimFrame打一次电话:
Rendering(0.9);
requestAnimFrame(render);参见示例,其中将答案的建议应用于问题的原始代码:
$("#a").on("change", function(){
Rendering(this.value);
})
function fcyclide(a, c, mu) {
var b = Math.sqrt(a * a - c * c);
return function (u, v, vector) {
var uu = 2 * u * Math.PI; var vv = 2 * v * Math.PI;
var cosu = Math.cos(uu); var cosv = Math.cos(vv);
var h = a - c * cosu * cosv;
var x = (mu * (c - a * cosu * cosv) + b * b * cosu) / h;
var y = (b * Math.sin(uu) * (a - mu * cosv)) / h;
var z = b * Math.sin(vv) * (c * cosu - mu) / h;
vector.x = x; vector.y = y; vector.z = z;
}
}
function addCyclide(object, a) {
var geom = new THREE.ParametricGeometry(fcyclide(a, 0.34, 0.56), 40, 40);
var material = new THREE.MeshNormalMaterial();
var mesh = new THREE.Mesh(geom, material);
object.add(mesh);
}
var scene = new THREE.Scene();
var aspect = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(70, aspect, 1, 10000);
camera.position.z = 4;
scene.add(camera);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var object = new THREE.Object3D()
scene.add(object);
window.onresize = resize;
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function render() {
renderer.render(scene, camera);
object.rotation.x += 0.001; object.rotation.y += 0.001;
requestAnimFrame(render);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function Rendering(a) {
object.children.splice(0); // clear scene
addCyclide(object, a);
}
Rendering(0.9);
requestAnimFrame(render);<script src="http://threejs.org/build/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label for="a">a: </label>
<input id="a" type="number" step="0.1" min="0.5" value="0.9"/>
https://stackoverflow.com/questions/51121645
复制相似问题