From b97ec30f0b51b892ebfcb5c7549e7511bcae7147 Mon Sep 17 00:00:00 2001 From: liteng <930372551@qq.com> Date: Mon, 26 Nov 2018 07:57:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B7=E6=9D=A1=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/editor/spline/SplineEditor.js | 253 ++++++++++++++++++ ShadowEditor.Web/src/polyfills.js | 8 + 2 files changed, 261 insertions(+) create mode 100644 ShadowEditor.Web/src/editor/spline/SplineEditor.js diff --git a/ShadowEditor.Web/src/editor/spline/SplineEditor.js b/ShadowEditor.Web/src/editor/spline/SplineEditor.js new file mode 100644 index 00000000..7103669e --- /dev/null +++ b/ShadowEditor.Web/src/editor/spline/SplineEditor.js @@ -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; \ No newline at end of file diff --git a/ShadowEditor.Web/src/polyfills.js b/ShadowEditor.Web/src/polyfills.js index fb61b3d1..629a8815 100644 --- a/ShadowEditor.Web/src/polyfills.js +++ b/ShadowEditor.Web/src/polyfills.js @@ -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; }; \ No newline at end of file