Commit 202bf85a authored by zz85's avatar zz85

AsciiRenderer

parent d3953369
<!doctype html>
<html lang="en">
<head>
<title>three.js ASCII - geometry - cube</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/Three.js"></script>
<script src="js/Stats.js"></script>
<script src="js/renderers/AsciiRenderer.js"></script>
<script>
// Just swap out the default CanvasRenderer -> AsciiRenderer and things should work
// Let's start with the class spinning cube example from three.js
var container, stats;
var camera, scene, renderer;
var cube, plane;
var targetYRotation = targetXRotation = 0;
var targetYRotationOnMouseDown = targetXRotationOnMouseDown = 0;
var mouseX = 0, mouseY = 0;
var mouseYOnMouseDown = mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild( info );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 500;
scene.add( camera );
// Cube
var materials = [];
for ( var i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) );
}
cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200, 1, 1, 1, materials ), new THREE.MeshFaceMaterial() );
cube.position.y = 150;
scene.add( cube );
// Plane
plane = new THREE.Mesh( new THREE.PlaneGeometry( 400, 400 ), new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ) );
scene.add( plane );
renderer = new THREE.ASCIIRenderer(); //THREE.CanvasRenderer
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
}
//
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
mouseYOnMouseDown = event.clientY - windowHalfY;
targetYRotationOnMouseDown = targetYRotation;
targetXRotationOnMouseDown = targetXRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetYRotation = targetYRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
targetXRotation = targetXRotationOnMouseDown + ( mouseY - mouseYOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;;
}
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
cube.rotation.x += ( targetXRotation - cube.rotation.x ) * 0.05;
plane.rotation.y = cube.rotation.y += ( targetYRotation - cube.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
</script>
</body>
</html>
\ No newline at end of file
/*
* @author zz85 / https://github.com/zz85
*
* Usage: Just replace your CanvasRenderer / WebGLRenderer with AsciiRenderer. The rest is magic.
*
* Ascii generation is based on http://www.nihilogic.dk/labs/jsascii/
* Maybe more about this later with a blog post at http://lab4games.net/zz85/blog
*
* 16 April 2012 - @blurspline
*/
THREE.ASCIIRenderer = function( renderer, charSet, options ) {
// its fun to create one your own!
charSet = (charSet === undefined) ? ' .:-=+*#%@' : charSet;
// ' .,:;=|iI+hHOE#`$';
// darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/
// ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split('');
if (!options) options = {};
// Some ASCII settings
var bResolution = !options['resolution'] ? 0.15 : options['resolution']; // Higher for more details
var iScale = !options['scale'] ? 1 : options['scale'];
var bColor = !options['color'] ? false : options['color']; // nice but slows down rendering!
var bAlpha = !options['alpha'] ? false : options['alpha']; // Transparency
var bBlock = !options['block'] ? false : options['block']; // blocked characters. like good O dos
var bInvert = !options['invert'] ? false : options['invert']; // black is white, white is black
var strResolution = 'low';
renderer = (renderer === undefined) ? THREE.CanvasRenderer : renderer; //THREE.WebGLRenderer
var canvasRenderer = new renderer();
var width, height;
var domElement = document.createElement('div');
var oAscii = document.createElement("table");
domElement.appendChild(oAscii);
var iWidth, iHeight;
var oImg;
this.setSize = function(w, h) {
width = w;
height = h;
canvasRenderer.setSize( w, h );
initAsciiSize();
};
this.render = function() {
canvasRenderer.render.apply(canvasRenderer, arguments);
asciifyImage(canvasRenderer, oAscii);
};
this.domElement = domElement;
// Throw in ascii library from http://www.nihilogic.dk/labs/jsascii/jsascii.js
/*
* jsAscii 0.1
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
* MIT License [http://www.nihilogic.dk/licenses/mit-license.txt]
*/
function initAsciiSize() {
iWidth = Math.round(width * fResolution);
iHeight = Math.round(height * fResolution);
oCanvas.width = iWidth;
oCanvas.height = iHeight;
// oCanvas.style.display = "none";
// oCanvas.style.width = iWidth;
// oCanvas.style.height = iHeight;
oImg = canvasRenderer.domElement;
if (oImg.style.backgroundColor) {
oAscii.rows[0].cells[0].style.backgroundColor = oImg.style.backgroundColor;
oAscii.rows[0].cells[0].style.color = oImg.style.color;
}
oAscii.cellSpacing = 0;
oAscii.cellPadding = 0;
var oStyle = oAscii.style;
oStyle.display = "inline";
oStyle.width = Math.round(iWidth/fResolution*iScale) + "px";
oStyle.height = Math.round(iHeight/fResolution*iScale) + "px";
oStyle.whiteSpace = "pre";
oStyle.margin = "0px";
oStyle.padding = "0px";
oStyle.letterSpacing = fLetterSpacing + "px";
oStyle.fontFamily = strFont;
oStyle.fontSize = fFontSize + "px";
oStyle.lineHeight = fLineHeight + "px";
oStyle.textAlign = "left";
oStyle.textDecoration = "none";
}
var aDefaultCharList = (" .,:;i1tfLCG08@").split("");
var aDefaultColorCharList = (" CGO08@").split("");
var strFont = "courier new, monospace";
var oCanvasImg = canvasRenderer.domElement;
var oCanvas = document.createElement("canvas");
if (!oCanvas.getContext) {
return;
}
var oCtx = oCanvas.getContext("2d");
if (!oCtx.getImageData) {
return;
}
var aCharList = (bColor ? aDefaultColorCharList : aDefaultCharList);
if (charSet) aCharList = charSet;
var fResolution = 0.5;
switch (strResolution) {
case "low" : fResolution = 0.25; break;
case "medium" : fResolution = 0.5; break;
case "high" : fResolution = 1; break;
}
if (bResolution) fResolution = bResolution;
// Setup dom
var fFontSize = (2/fResolution)*iScale;
var fLineHeight = (2/fResolution)*iScale;
// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.
var fLetterSpacing = 0;
if (strResolution == "low") {
switch (iScale) {
case 1 : fLetterSpacing = -1; break;
case 2 :
case 3 : fLetterSpacing = -2.1; break;
case 4 : fLetterSpacing = -3.1; break;
case 5 : fLetterSpacing = -4.15; break;
}
}
if (strResolution == "medium") {
switch (iScale) {
case 1 : fLetterSpacing = 0; break;
case 2 : fLetterSpacing = -1; break;
case 3 : fLetterSpacing = -1.04; break;
case 4 :
case 5 : fLetterSpacing = -2.1; break;
}
}
if (strResolution == "high") {
switch (iScale) {
case 1 :
case 2 : fLetterSpacing = 0; break;
case 3 :
case 4 :
case 5 : fLetterSpacing = -1; break;
}
}
// can't get a span or div to flow like an img element, but a table works?
// convert img element to ascii
function asciifyImage(canvasRenderer, oAscii)
{
oCtx.clearRect(0, 0, iWidth, iHeight);
oCtx.drawImage(oCanvasImg, 0, 0, iWidth, iHeight);
var oImgData = oCtx.getImageData(0, 0, iWidth, iHeight).data;
// Coloring loop starts now
var strChars = "";
// console.time('rendering');
for (var y=0;y<iHeight;y+=2) {
for (var x=0;x<iWidth;x++) {
var iOffset = (y*iWidth + x) * 4;
var iRed = oImgData[iOffset];
var iGreen = oImgData[iOffset + 1];
var iBlue = oImgData[iOffset + 2];
var iAlpha = oImgData[iOffset + 3];
var iCharIdx;
var fBrightness;
fBrightness = (0.3*iRed + 0.59*iGreen + 0.11*iBlue) / 255;
// fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255;
if (iAlpha == 0) {
// should calculate alpha instead, but quick hack :)
//fBrightness *= (iAlpha / 255);
fBrightness = 1;
}
iCharIdx = Math.floor((1-fBrightness) * (aCharList.length-1));
if (bInvert) {
iCharIdx = aCharList.length - iCharIdx - 1;
}
// good for debugging
//fBrightness = Math.floor(fBrightness * 10);
//strThisChar = fBrightness;
var strThisChar = aCharList[iCharIdx];
if (strThisChar===undefined || strThisChar == " ")
strThisChar = "&nbsp;";
if (bColor) {
strChars += "<span style='"
+ "color:rgb("+iRed+","+iGreen+","+iBlue+");"
+ (bBlock ? "background-color:rgb("+iRed+","+iGreen+","+iBlue+");" : "")
+ (bAlpha ? "opacity:" + (iAlpha/255) + ";" : "")
+ "'>" + strThisChar + "</span>";
} else {
strChars += strThisChar;
}
}
strChars += "<br/>";
}
oAscii.innerHTML = "<tr><td>" + strChars + "</td></tr>";
// console.timeEnd('rendering');
// return oAscii;
}
// end modified asciifyImage block
};
\ No newline at end of file
......@@ -22,7 +22,7 @@ THREE.ParametricGeometries = {
x = 3 * cos(u) * (1 + sin(u)) + (2 * (1 - cos(u) / 2)) * cos(v + pi);
z = -8 * sin(u);
}
y = -2 * (1 - cos(u) / 2) * sin(v);
return new THREE.Vector3(x, y, z);
......@@ -32,7 +32,7 @@ THREE.ParametricGeometries = {
return function(u, v) {
var x = u * width;
var y = 0;
var y = 0;
var z = v * height;
console.log(x, y, z);
......@@ -64,8 +64,8 @@ THREE.ParametricGeometries = {
u *= pi;
t *= 2 * pi;
u = u * 2
var phi = u / 2
u = u * 2;
var phi = u / 2;
var major = 2.25, a = 0.125, b = 0.65;
var x, y, z;
x = a * cos(t) * cos(phi) - b * sin(t) * sin(phi);
......@@ -173,7 +173,7 @@ THREE.TubeGeometry2.prototype.constructor = THREE.TubeGeometry2;
t *= Math.PI * 2;
var r = 0.5;
var tx = (1 + r * Math.cos(q * t)) * Math.cos(p * t),
ty = (1 + r * Math.cos(q * t)) * Math.sin(p * t),
tz = r * Math.sin(q * t);
......@@ -187,7 +187,7 @@ THREE.TubeGeometry2.prototype.constructor = THREE.TubeGeometry2;
var radiusSegments = segmentsT;
var extrudePath = new TorusKnotCurve();
THREE.TubeGeometry2.call( this, extrudePath, segments, tube, radiusSegments, true, false );
THREE.TubeGeometry2.call( this, extrudePath, segments, tube, radiusSegments, true, false );
};
......@@ -222,7 +222,7 @@ THREE.PlaneGeometry2 = function(width, depth, segmentsWidth, segmentsDepth) {
function plane(u, v) {
var x = u * width;
var y = 0;
var y = 0;
var z = v * depth;
return new THREE.Vector3(x, y, z);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment