Skip to content

Instantly share code, notes, and snippets.

@shshaw
Last active January 3, 2017 19:22
Show Gist options
  • Save shshaw/7a4a8d2b0b160c1a90dcc6b8d79788da to your computer and use it in GitHub Desktop.
Save shshaw/7a4a8d2b0b160c1a90dcc6b8d79788da to your computer and use it in GitHub Desktop.
Toast & Butter
<script>console.clear();</script>
var renderCalls = [];
function render () {
requestAnimationFrame( render );
renderCalls.forEach((callback)=>{ callback(); });
}
render();
/*////////////////////////////////////////*/
const HALFPI = Math.PI / 2;
const TWOPI = Math.PI * 2;
/*////////////////////////////////////////*/
var world;
var dt = 1 / 60;
var constraintDown = false;
var camera, scene, renderer, gplane=false, clickMarker=false;
var geometry, material, mesh;
var controls,time = Date.now();
var camera, scene, renderer;
initCannon();
init();
function init() {
// scene
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xFFFFFF, 100, 250 );
// camera
camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 0.5, 10000 );
camera.position.set(0, 40, 90);
camera.quaternion.setFromAxisAngle(new THREE.Vector3(0,1,0), Math.PI/2);
scene.add(camera);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
document.body.appendChild( renderer.domElement );
renderer.gammaInput = true;
renderer.gammaOutput = true;
if ( window.innerWidth > 500 ) {
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
console.log(renderer.shadowMap);
}
renderCalls.push(function(){ renderer.render(scene, camera); });
window.addEventListener( 'resize', onWindowResize, false );
let orbit = new THREE.OrbitControls(camera, renderer.domElement);
orbit.zoomSpeed = 0.6;
orbit.minDistance = 10;
/*////////////////////////////////////////*/
// lights
var light, materials;
var ambientLight = new THREE.AmbientLight(0x222222);
scene.add(ambientLight);
/*////////////////////////////////////////*/
light = new THREE.SpotLight( 0xffffff );
light.position.y = 100;
light.position.x = 0;
light.position.z = 65; //110;
light.power = 2;
light.angle = Math.PI / 2.5; //Math.PI / 4;
light.castShadow = true;
light.shadow.mapSize.width = 4096;
light.shadow.mapSize.height = 4096;
light.shadow.camera.near = 0.1;
light.shadow.camera.far = 100;
light.shadow.camera.fov = 20;
scene.add( light );
let geometry = new THREE.PlaneGeometry( 400, 400, 1, 1 );
let material = new THREE.MeshPhongMaterial({
color: 0xFFFFFF,
emissive: 0xFFFFFF,
emissiveIntensity: 0.2,
shininess: 400,
shading: THREE.SmoothShading
});
mesh = new THREE.Mesh( geometry, material );
//plane.rotation.x = Math.PI / -2;
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.quaternion.setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI / 2);
scene.add(mesh);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function initCannon(){
// Setup our world
world = new CANNON.World();
world.quatNormalizeSkip = 0;
world.quatNormalizeFast = false;
world.gravity.set(0,-10,0);
world.broadphase = new CANNON.NaiveBroadphase();
// Create a plane
var groundShape = new CANNON.Plane();
var groundBody = new CANNON.Body({ mass: 0 });
groundBody.addShape(groundShape);
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2);
world.add(groundBody);
// Joint body
var shape = new CANNON.Sphere(0.1);
jointBody = new CANNON.Body({ mass: 0 });
jointBody.addShape(shape);
jointBody.collisionFilterGroup = 0;
jointBody.collisionFilterMask = 0;
world.add(jointBody);
// // Create a sphere
// var mass = 5, radius = 0.3;
// sphereShape = new CANNON.Sphere(radius);
// sphereBody = new CANNON.Body({ mass: mass });
// sphereBody.addShape(sphereShape);
// sphereBody.position.set(0,0,0);
// sphereBody.linearDamping = 0.9;
// world.add(sphereBody);
}
function updatePhysics(){ world.step(dt); }
renderCalls.push(updatePhysics);
/*////////////////////////////////////////*/
function noiseMap(size,intensity){
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
width = canvas.width = size || 512,
height = canvas.height = size || 512;
intensity = intensity || 120;
var imageData = ctx.getImageData(0, 0, width, height),
pixels = imageData.data,
n = pixels.length,
i = 0;
while (i < n) {
pixels[i++] = pixels[i++] = pixels[i++] = Math.sin( i * i * i + (i/n) * Math.PI) * intensity;
pixels[i++] = 255;
}
ctx.putImageData(imageData, 0, 0);
let sprite = new THREE.Texture(canvas);
sprite.needsUpdate = true;
return sprite;
}
/*////////////////////////////////////////*/
const toastHeight = 8;
const toastWidth = 8;
const toastDepth = 1;
const toastHeightSegments = 8;
const toastWidthSegments = 5;
const toastGeo = new THREE.BoxGeometry( toastWidth, toastHeight, toastDepth, toastWidthSegments, toastHeightSegments );
toastGeo.vertices.forEach((vertex,i)=>{
let offsetX = (vertex.y * -0.06);
let offsetY = 0;
if ( vertex.y === toastHeight / 2 ) {
offsetY = -0.4 + 0.5 * Math.cos((vertex.x / (toastWidthSegments-1)) * HALFPI);
offsetX = ( Math.abs(vertex.x) > 1 ? -0.5 : -0.25 );
} else if ( vertex.y > (toastHeight / 2) * 0.25 ) {// (toastHeightSegments/2) ) {
offsetX = 0.4 * Math.sin((vertex.y / (toastHeightSegments /2)) * Math.PI);
}
vertex.x += offsetX * ( vertex.x < 0 ? -1 : 1 );
vertex.y += offsetY;
});
// Color the outside of the toast
let color = 0x630A10; //Math.random() * 0xffffff;
for (var i = 0; i < (toastHeightSegments * 4) + ( toastWidthSegments * 4); i++) {
toastGeo.faces[i].color.setHex( color );
}
var toastMaterial = new THREE.MeshPhongMaterial( {
color: 0xFFDD83, //0xFFDD83,
vertexColors: THREE.FaceColors,
bumpMap: noiseMap(256,10),
bumpMapScale: 2,
//wireframe: true,
shininess: 0
});
function Toast(){
THREE.Mesh.call(this, toastGeo, toastMaterial);
};
Toast.prototype = Object.create(THREE.Mesh.prototype);
/*////////////////////////////////////////*/
function PhysicalBox(opts) {
if (!(this instanceof PhysicalBox)) { return new PhysicalBox(opts); }
opts = opts || this.defaultOpts;
CANNON.Body.call(this, opts);
this.object = new THREE.Object3D();
this.sync = this.sync.bind(this);
}
PhysicalBox.prototype = Object.assign(Object.create(CANNON.Body.prototype),{
constructor: PhysicalBox,
defaultOpts: { mass: 100 },
add: function(obj){
this.object.add(obj); //.apply(this.object, arguments);
this.updateShape();
},
updateShape: function(){
let bbox = new THREE.Box3().setFromObject(this.object);
this.shapes = [];
this.addShape(new CANNON.Box( new CANNON.Vec3( bbox.max.x, bbox.max.y, bbox.max.z) ));
},
sync: function(){
if ( this.position && this.object ) {
this.object.position.copy( this.position );
this.object.quaternion.copy( this.quaternion );
}
}
});
/*////////////////////////////////////////*/
function makeToast(){
let c3d = new PhysicalBox({ mass: 100 });
let toast = new Toast();
toast.castShadow = true;
toast.receiveShadow = true;
c3d.add(toast);
world.add(c3d);
scene.add(c3d.object);
renderCalls.push(c3d.sync);
return c3d;
}
const butterGeometry = new THREE.BoxGeometry( 3, 3, 0.5 );
const butterMaterial = new THREE.MeshPhongMaterial( { color: 0xFBFF64, shininess: 50 } );
function makeButter(){
let c3d = new PhysicalBox({ mass: 20 });
let butter = new THREE.Mesh( butterGeometry, butterMaterial );
butter.castShadow = true;
butter.receiveShadow = true;
c3d.add(butter);
world.add(c3d);
scene.add(c3d.object);
renderCalls.push(c3d.sync);
return c3d;
}
/*////////////////////////////////////////*/
for (var i = 0, len = 21; i < len; i++){
let c3d = ( i % 2 ? makeButter() : makeToast() );
if ( i === 0 ) { console.log(c3d); }
c3d.position.set((Math.random() - 0.5) * 10, 40 + (i * 8), (Math.random() - 0.5 )* 20);
c3d.quaternion.setFromEuler(Math.random() * TWOPI, 0, Math.random() * HALFPI);
//c3d.velocity.set(19 * Math.sin((i / len) * TWOPI), 8, 5 * (Math.random() - 0.5));
}
<script src="http://codepen.io/shshaw/pen/epmrgO"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
canvas { display: block; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment