Last active
April 18, 2021 03:29
-
-
Save benursu/f4e71ec9b9173c9aaf2044c92b28a85e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>three.js webgl - exporter - obj</title> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | |
<link type="text/css" rel="stylesheet" href="main.css"> | |
<style> | |
.floating { | |
background : #000000; | |
opacity : 0.8; | |
width : 80%; | |
height : 80%; | |
position : absolute; | |
left : 10%; | |
top : 10%; | |
border : 1px solid #555555; | |
padding : 10px; | |
display : none; | |
overflow : auto; | |
z-index: 100; | |
} | |
</style> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> | |
</head> | |
<body> | |
<div id="info"> | |
<!-- <button id="triangle">triangle</button> | |
<button id="cube">cube</button> | |
<button id="cylinder">cylinder</button> | |
<button id="multiple">multiple</button> | |
<button id="transformed">transformed</button><br /><br /> --> | |
<button id="loadNotes">Load Notes</button> | |
<button id="loadNotesParticles">Load Notes Particles</button> | |
<button id="exportNotes">Export Notes</button> | |
<button id="exportNotesParticles">Export Notes Particles</button> | |
</div> | |
<script type="module"> | |
import * as THREE from './build/three.module.js'; | |
import { OBJExporter } from './jsm/exporters/OBJExporter.js'; | |
import { ColladaExporter } from './jsm/exporters/ColladaExporter.js'; | |
import { TrackballControls } from './jsm/controls/TrackballControls.js'; | |
var camera, controls, scene, light, renderer; | |
var loadNotesButton, loadNotesParticlesButton, exportNotesButton, exportNotesParticlesButton, floatingDiv; | |
var mouseX = 0, mouseY = 0; | |
//create midi | |
//convert to text here (TimestampType Absolute): http://flashmusicgames.com/midi/mid2txt.php | |
//online sequencer for troubleshooting: https://onlinesequencer.net/import | |
//mario-bros midi: https://bitmidi.com/mario-bros-super-mario-bros-theme-mid | |
//tetris midi: https://bitmidi.com/tetris-tetris-main-theme-mid | |
// | |
var midiLocation = 'midi/tetris.txt'; | |
var material = new THREE.MeshLambertMaterial( { color: 0x00cc00 } ); | |
var notes = []; | |
var notesTemp = {}; | |
function loadNotes() { | |
$.ajax({ | |
url : midiLocation, | |
dataType: 'text', | |
success : function (data) { | |
//parse data | |
var lineByLine = data.split("\n"); | |
for(var i = 0; i < lineByLine.length; i++){ | |
var lineData = lineByLine[i].split(' '); | |
var timestamp = lineData[0]; | |
var signal = lineData[1]; | |
var note = lineData[3]; | |
var velocity = lineData[4]; | |
if(signal == 'On' || signal == 'Off'){ | |
var noteKey = note.split('=')[1]; | |
if(velocity.substring(0, 3) == 'v=0'){ | |
//off | |
var duration = timestamp - notesTemp[noteKey].timestamp; | |
var noteData = { timestamp: parseInt(notesTemp[noteKey].timestamp), note: parseInt(noteKey), duration: duration }; | |
notes.push(noteData); | |
delete notesTemp[noteKey]; | |
}else{ | |
//on | |
var noteData = { timestamp: timestamp, note: noteKey }; | |
notesTemp[noteKey] = noteData; | |
} | |
} | |
} | |
//build notes | |
for(var i = 0; i < notes.length; i++){ | |
var geometry = new THREE.BoxBufferGeometry( 10, notes[i].duration, 10 ); | |
geometry.translate(0, notes[i].duration/2, 0); | |
var mesh = new THREE.Mesh(geometry, material); | |
mesh.position.x = notes[i].note * 10; | |
mesh.position.y = notes[i].timestamp; | |
scene.add(mesh); | |
} | |
} | |
}); | |
} | |
function loadNotesParticles() { | |
$.ajax({ | |
url : midiLocation, | |
dataType: 'text', | |
success : function (data) { | |
//parse data | |
var lineByLine = data.split("\n"); | |
for(var i = 0; i < lineByLine.length; i++){ | |
var lineData = lineByLine[i].split(' '); | |
var timestamp = lineData[0]; | |
var signal = lineData[1]; | |
var note = lineData[3]; | |
var velocity = lineData[4]; | |
if(signal == 'On' || signal == 'Off'){ | |
var noteKey = note.split('=')[1]; | |
if(velocity.substring(0, 3) == 'v=0'){ | |
//off | |
var duration = timestamp - notesTemp[noteKey].timestamp; | |
var noteData = { timestamp: parseInt(notesTemp[noteKey].timestamp), note: parseInt(noteKey), duration: duration }; | |
notes.push(noteData); | |
delete notesTemp[noteKey]; | |
}else{ | |
//on | |
var noteData = { timestamp: timestamp, note: noteKey }; | |
notesTemp[noteKey] = noteData; | |
} | |
} | |
} | |
//build notes particles | |
// console.log(notes); | |
for(var i = 0; i < notes.length; i++){ | |
var geometry = new THREE.PlaneBufferGeometry(1, 1); | |
var mesh = new THREE.Mesh(geometry, material); | |
mesh.name = 'NoteOn-' + i; | |
mesh.position.x = notes[i].note * 10; | |
mesh.position.y = notes[i].timestamp; | |
scene.add(mesh); | |
var geometry = new THREE.PlaneBufferGeometry(1, 1); | |
var mesh = new THREE.Mesh(geometry, material); | |
mesh.name = 'NoteOff-' + i; | |
mesh.position.x = notes[i].note * 10; | |
mesh.position.y = notes[i].timestamp + notes[i].duration; | |
scene.add(mesh); | |
} | |
console.log('total notes: ' + notes.length); | |
} | |
}); | |
} | |
function exportToNotes() { | |
var exporter = new OBJExporter(); | |
var result = exporter.parse( scene ); | |
// floatingDiv.style.display = 'block'; | |
// floatingDiv.innerHTML = result.split( '\n' ).join( '<br />' ); | |
$.ajax({ | |
url: '/receiveNotes', | |
data: result, | |
cache: false, | |
contentType: false, | |
processData: false, | |
method: 'POST', | |
type: 'POST', | |
success: function(data){ | |
// alert(data); | |
console.log('success'); | |
} | |
}); | |
} | |
function exportToNotesParticles() { | |
var exporter = new ColladaExporter(); | |
var result = exporter.parse( scene ); | |
// floatingDiv.style.display = 'block'; | |
// floatingDiv.innerHTML = result.split( '\n' ).join( '<br />' ); | |
$.ajax({ | |
url: '/receiveNotesParticles', | |
data: result.data, | |
cache: false, | |
contentType: false, | |
processData: false, | |
method: 'POST', | |
type: 'POST', | |
success: function(data){ | |
// alert(data); | |
console.log('success'); | |
} | |
}); | |
} | |
function init() { | |
renderer = new THREE.WebGLRenderer(); | |
renderer.setPixelRatio( window.devicePixelRatio ); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
document.body.appendChild( renderer.domElement ); | |
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 100000 ); | |
camera.position.set( 0, 0, 400 ); | |
controls = new TrackballControls( camera, renderer.domElement ); | |
controls.rotateSpeed = 1.0; | |
controls.zoomSpeed = 1.2; | |
controls.panSpeed = 0.8; | |
scene = new THREE.Scene(); | |
light = new THREE.DirectionalLight( 0xffffff ); | |
scene.add( light ); | |
window.addEventListener( 'click', onWindowClick, false ); | |
window.addEventListener( 'resize', onWindowResize, false ); | |
document.addEventListener( 'mousemove', onDocumentMouseMove, false ); | |
document.addEventListener( 'mouseover', onDocumentMouseMove, false ); | |
loadNotesButton = document.getElementById('loadNotes'); | |
loadNotesButton.addEventListener( 'click', function () { | |
loadNotes(); | |
} ); | |
loadNotesParticlesButton = document.getElementById('loadNotesParticles'); | |
loadNotesParticlesButton.addEventListener( 'click', function () { | |
loadNotesParticles(); | |
} ); | |
exportNotesButton = document.getElementById('exportNotes'); | |
exportNotesButton.addEventListener( 'click', function () { | |
exportToNotes(); | |
} ); | |
exportNotesParticlesButton = document.getElementById('exportNotesParticles'); | |
exportNotesParticlesButton.addEventListener( 'click', function () { | |
exportToNotesParticles(); | |
} ); | |
floatingDiv = document.createElement( 'div' ); | |
floatingDiv.className = 'floating'; | |
document.body.appendChild( floatingDiv ); | |
} | |
function onWindowClick( event ) { | |
var needToClose = true; | |
var target = event.target; | |
while ( target !== null ) { | |
if ( target === floatingDiv || target === loadNotesButton || target === loadNotesParticlesButton || target === exportNotesButton || target === exportNotesParticlesButton ) { | |
needToClose = false; | |
break; | |
} | |
target = target.parentElement; | |
} | |
if ( needToClose ) { | |
floatingDiv.style.display = 'none'; | |
} | |
} | |
function onWindowResize() { | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
} | |
function onDocumentMouseMove( event ) { | |
var windowHalfX = window.innerWidth / 2; | |
var windowHalfY = window.innerHeight / 2; | |
mouseX = ( event.clientX - windowHalfX ) / 2; | |
mouseY = ( event.clientY - windowHalfY ) / 2; | |
} | |
function animate() { | |
requestAnimationFrame( animate ); | |
controls.update(); | |
light.position.set( camera.position.x, camera.position.y, camera.position.z ).normalize(); | |
renderer.render( scene, camera ); | |
} | |
function generateTriangleGeometry() { | |
var geometry = new THREE.BufferGeometry(); | |
var vertices = []; | |
vertices.push( - 50, - 50, 0 ); | |
vertices.push( 50, - 50, 0 ); | |
vertices.push( 50, 50, 0 ); | |
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) ); | |
geometry.computeVertexNormals(); | |
return geometry; | |
} | |
init(); | |
animate(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice job