Skip to content

Instantly share code, notes, and snippets.

@benursu
Last active April 18, 2021 03:29
Show Gist options
  • Save benursu/f4e71ec9b9173c9aaf2044c92b28a85e to your computer and use it in GitHub Desktop.
Save benursu/f4e71ec9b9173c9aaf2044c92b28a85e to your computer and use it in GitHub Desktop.
<!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>
@itxtoledo
Copy link

nice job

@A7EXkaa
Copy link

A7EXkaa commented Apr 18, 2021

Perfect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment