样条编辑器。

This commit is contained in:
liteng 2018-11-26 07:57:56 +08:00
parent 1d072cec82
commit b97ec30f0b
2 changed files with 261 additions and 0 deletions

View File

@ -0,0 +1,253 @@
var container, stats;
var camera, scene, renderer;
var splineHelperObjects = [];
var splinePointsLength = 4;
var positions = [];
var point = new THREE.Vector3();
var geometry = new THREE.BoxBufferGeometry(20, 20, 20);
var transformControl;
var ARC_SEGMENTS = 200;
var splines = {};
var params = {
uniform: true,
tension: 0.5,
centripetal: true,
chordal: true,
addPoint: addPoint,
removePoint: removePoint,
exportSpline: exportSpline
};
function SplineEditor(container) {
container = document.getElementById('container');
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 250, 1000);
scene.add(camera);
scene.add(new THREE.AmbientLight(0xf0f0f0));
var light = new THREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 1500, 200);
light.castShadow = true;
light.shadow = new THREE.LightShadow(new THREE.PerspectiveCamera(70, 1, 200, 2000));
light.shadow.bias = - 0.000222;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
var planeGeometry = new THREE.PlaneBufferGeometry(2000, 2000);
planeGeometry.rotateX(- Math.PI / 2);
var planeMaterial = new THREE.ShadowMaterial({ opacity: 0.2 });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = - 200;
plane.receiveShadow = true;
scene.add(plane);
var helper = new THREE.GridHelper(2000, 100);
helper.position.y = - 199;
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
//var axes = new THREE.AxesHelper( 1000 );
//axes.position.set( - 500, - 500, - 500 );
//scene.add( axes );
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI();
gui.add(params, 'uniform');
gui.add(params, 'tension', 0, 1).step(0.01).onChange(function (value) {
splines.uniform.tension = value;
updateSplineOutline();
});
gui.add(params, 'centripetal');
gui.add(params, 'chordal');
gui.add(params, 'addPoint');
gui.add(params, 'removePoint');
gui.add(params, 'exportSpline');
gui.open();
// Controls
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.damping = 0.2;
controls.addEventListener('change', render);
controls.addEventListener('start', function () {
cancelHideTransorm();
});
controls.addEventListener('end', function () {
delayHideTransform();
});
transformControl = new THREE.TransformControls(camera, renderer.domElement);
transformControl.addEventListener('change', render);
transformControl.addEventListener('dragging-changed', function (event) {
controls.enabled = !event.value;
});
scene.add(transformControl);
// Hiding transform situation is a little in a mess :()
transformControl.addEventListener('change', function () {
cancelHideTransorm();
});
transformControl.addEventListener('mouseDown', function () {
cancelHideTransorm();
});
transformControl.addEventListener('mouseUp', function () {
delayHideTransform();
});
transformControl.addEventListener('objectChange', function () {
updateSplineOutline();
});
var dragcontrols = new THREE.DragControls(splineHelperObjects, camera, renderer.domElement); //
dragcontrols.enabled = false;
dragcontrols.addEventListener('hoveron', function (event) {
transformControl.attach(event.object);
cancelHideTransorm();
});
dragcontrols.addEventListener('hoveroff', function () {
delayHideTransform();
});
var hiding;
function delayHideTransform() {
cancelHideTransorm();
hideTransform();
}
function hideTransform() {
hiding = setTimeout(function () {
transformControl.detach(transformControl.object);
}, 2500);
}
function cancelHideTransorm() {
if (hiding) clearTimeout(hiding);
}
/*******
* Curves
*********/
for (var i = 0; i < splinePointsLength; i++) {
addSplineObject(positions[i]);
}
positions = [];
for (var i = 0; i < splinePointsLength; i++) {
positions.push(splineHelperObjects[i].position);
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(ARC_SEGMENTS * 3), 3));
var curve = new THREE.CatmullRomCurve3(positions);
curve.curveType = 'catmullrom';
curve.mesh = new THREE.Line(geometry.clone(), new THREE.LineBasicMaterial({
color: 0xff0000,
opacity: 0.35
}));
curve.mesh.castShadow = true;
splines.uniform = curve;
curve = new THREE.CatmullRomCurve3(positions);
curve.curveType = 'centripetal';
curve.mesh = new THREE.Line(geometry.clone(), new THREE.LineBasicMaterial({
color: 0x00ff00,
opacity: 0.35
}));
curve.mesh.castShadow = true;
splines.centripetal = curve;
curve = new THREE.CatmullRomCurve3(positions);
curve.curveType = 'chordal';
curve.mesh = new THREE.Line(geometry.clone(), new THREE.LineBasicMaterial({
color: 0x0000ff,
opacity: 0.35
}));
curve.mesh.castShadow = true;
splines.chordal = curve;
for (var k in splines) {
var spline = splines[k];
scene.add(spline.mesh);
}
load([new THREE.Vector3(289.76843686945404, 452.51481137238443, 56.10018915737797),
new THREE.Vector3(- 53.56300074753207, 171.49711742836848, - 14.495472686253045),
new THREE.Vector3(- 91.40118730204415, 176.4306956436485, - 6.958271935582161),
new THREE.Vector3(- 383.785318791128, 491.1365363371675, 47.869296953772746)]);
}
SplineEditor.prototype.addSplineObject = function (position) {
var material = new THREE.MeshLambertMaterial({ color: Math.random() * 0xffffff });
var object = new THREE.Mesh(geometry, material);
if (position) {
object.position.copy(position);
} else {
object.position.x = Math.random() * 1000 - 500;
object.position.y = Math.random() * 600;
object.position.z = Math.random() * 800 - 400;
}
object.castShadow = true;
object.receiveShadow = true;
scene.add(object);
splineHelperObjects.push(object);
return object;
};
SplineEditor.prototype.addPoint = function () {
splinePointsLength++;
positions.push(addSplineObject().position);
updateSplineOutline();
};
SplineEditor.prototype.removePoint = function () {
if (splinePointsLength <= 4) {
return;
}
splinePointsLength--;
positions.pop();
scene.remove(splineHelperObjects.pop());
updateSplineOutline();
};
SplineEditor.prototype.updateSplineOutline = function () {
for (var k in splines) {
var spline = splines[k];
var splineMesh = spline.mesh;
var position = splineMesh.geometry.attributes.position;
for (var i = 0; i < ARC_SEGMENTS; i++) {
var t = i / (ARC_SEGMENTS - 1);
spline.getPoint(t, point);
position.setXYZ(i, point.x, point.y, point.z);
}
position.needsUpdate = true;
}
};
SplineEditor.prototype.exportSpline = function () {
var strplace = [];
for (var i = 0; i < splinePointsLength; i++) {
var p = splineHelperObjects[i].position;
strplace.push('new THREE.Vector3({0}, {1}, {2})'.format(p.x, p.y, p.z));
}
console.log(strplace.join(',\n'));
var code = '[' + (strplace.join(',\n\t')) + ']';
prompt('copy and paste code', code);
}
SplineEditor.prototype.load = function (new_positions) {
while (new_positions.length > positions.length) {
addPoint();
}
while (new_positions.length < positions.length) {
removePoint();
}
for (var i = 0; i < positions.length; i++) {
positions[i].copy(new_positions[i]);
}
updateSplineOutline();
};
SplineEditor.prototype.animate = function () {
requestAnimationFrame(animate);
render();
stats.update();
};
SplineEditor.prototype.render = function () {
splines.uniform.mesh.visible = params.uniform;
splines.centripetal.mesh.visible = params.centripetal;
splines.chordal.mesh.visible = params.chordal;
renderer.render(scene, camera);
};
export default SplineEditor;

View File

@ -3,4 +3,12 @@ window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.Mo
Number.prototype.format = function () {
return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};
String.prototype.format = function () {
var str = this;
for (var i = 0; i < arguments.length; i++) {
str = str.replace('{' + i + '}', arguments[i]);
}
return str;
};