Skip to content
This repository was archived by the owner on Jul 20, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { configure } from '@kadira/storybook';

configure(function () {
require('./stories/Examples/webgl.stories.js');
require('./stories/Examples/advanced.stories.js');
require('./stories/Examples/benchmark.stories.js');
}, module);
Binary file added .storybook/public/textures/UV_Grid_Sm.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions .storybook/publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

set -e

rm -rf pages/{storybook,.git}
./node_modules/.bin/build-storybook -o pages/storybook -s .storybook/public

cd pages
git init
git add .
git commit -m 'Build Storybook'
git push --force https://github.com/toxicFork/react-three-renderer master:gh-pages
rm -rf .git
71 changes: 71 additions & 0 deletions .storybook/stories/Examples/AdvancedExample/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// see advanced.html :)

import React from 'react';
import React3Renderer from 'react-three-renderer/lib/React3Renderer';
import THREE from 'three';

// ^ Look mom, no react-dom!

const canvas = document.getElementById('canvas');

const react3Renderer = new React3Renderer();

const width = 800;
const height = 600;

const cameraPosition = new THREE.Vector3(0, 0, 5);

let cubeRotation = new THREE.Euler();

function onRecreateCanvas() {
// no need to deal with this now, but here we'd need to create a new canvas and
// re-render the scene there.
}

function animate() {
cubeRotation = new THREE.Euler(
cubeRotation.x + 0.1,
cubeRotation.y + 0.1,
0
);

react3Renderer.render(<react3
width={width}
height={height}

onRecreateCanvas={onRecreateCanvas}

context="3d"

antialias
mainCamera="camera"
>
<scene>
<perspectiveCamera
name="camera"
fov={75}
aspect={width / height}
near={0.1}
far={1000}

position={cameraPosition}
/>
<mesh
rotation={cubeRotation}
>
<boxGeometry
width={1}
height={1}
depth={1}
/>
<meshBasicMaterial
color={0xff0000}
/>
</mesh>
</scene>
</react3>, canvas);

requestAnimationFrame(animate);
}

animate();
139 changes: 139 additions & 0 deletions .storybook/stories/Examples/AnimationCloth/Cloth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Cloth Simulation using a relaxed constrains solver
*/

// Suggested Readings

// Advanced Character Physics by Thomas Jakobsen Character
// http://freespace.virgin.net/hugo.elias/models/m_cloth.htm
// http://en.wikipedia.org/wiki/Cloth_modeling
// http://cg.alexandra.dk/tag/spring-mass-system/
// Real-time Cloth Animation http://www.darwin3d.com/gamedev/articles/col0599.pdf
import THREE from 'three';


function plane(width, height) {
return (u, v) => {
const x = (u - 0.5) * width;
const y = (v + 0.5) * height;
const z = 0;

return new THREE.Vector3(x, y, z);
};
}

const DAMPING = 0.03;
const DRAG = 1 - DAMPING;
const MASS = 0.1;
const restDistance = 25;

const xSegs = 10; //
const ySegs = 10; //

const clothFunction = plane(restDistance * xSegs, restDistance * ySegs);

class Particle {
constructor(x, y, z, mass) {
void z;

this.position = clothFunction(x, y); // position
this.previous = clothFunction(x, y); // previous
this.original = clothFunction(x, y);
this.a = new THREE.Vector3(0, 0, 0); // acceleration
this.mass = mass;
this.invMass = 1 / mass;
this.tmp = new THREE.Vector3();
this.tmp2 = new THREE.Vector3();
}

// Force -> Acceleration
addForce(force) {
this.a.add(
this.tmp2.copy(force).multiplyScalar(this.invMass)
);
}

// Performs verlet integration
integrate(timesQ) {
const newPos = this.tmp.subVectors(this.position, this.previous);
newPos.multiplyScalar(DRAG).add(this.position);
newPos.add(this.a.multiplyScalar(timesQ));

this.tmp = this.previous;
this.previous = this.position;
this.position = newPos;

this.a.set(0, 0, 0);
}
}

class Cloth {
static clothFunction = clothFunction;
static MASS = MASS;

constructor(w = 10, h = 10) {
this.w = w;
this.h = h;

const particles = [];
const constrains = [];

let u;
let v;

// Create particles
for (v = 0; v <= h; v++) {
for (u = 0; u <= w; u++) {
particles.push(
new Particle(u / w, v / h, 0, MASS)
);
}
}

function index(indexU, indexV) {
return indexU + indexV * (w + 1);
}

// Structural

for (v = 0; v < h; v++) {
for (u = 0; u < w; u++) {
constrains.push([
particles[index(u, v)],
particles[index(u, v + 1)],
restDistance,
]);

constrains.push([
particles[index(u, v)],
particles[index(u + 1, v)],
restDistance,
]);
}
}

for (u = w, v = 0; v < h; v++) {
constrains.push([
particles[index(u, v)],
particles[index(u, v + 1)],
restDistance,
]);
}

for (v = h, u = 0; u < w; u++) {
constrains.push([
particles[index(u, v)],
particles[index(u + 1, v)],
restDistance,
]);
}


this.particles = particles;
this.constrains = constrains;

this.index = index;
}
}

export default Cloth;
37 changes: 37 additions & 0 deletions .storybook/stories/Examples/AnimationCloth/ClothGeometry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

const { PropTypes } = React;

import Cloth from './Cloth';

import PureRenderMixin from 'react/lib/ReactComponentWithPureRenderMixin';

class ClothGeometry extends React.Component {
static propTypes = {
cloth: PropTypes.instanceOf(Cloth).isRequired,
};

componentDidMount() {
const geometry = this.refs.geometry;

geometry.computeFaceNormals();
}

shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate;

render() {
const {
cloth,
} = this.props;

return (<parametricGeometry
ref={'geometry'}
parametricFunction={Cloth.clothFunction}
slices={cloth.w}
stacks={cloth.h}
dynamic
/>);
}
}

export default ClothGeometry;
72 changes: 72 additions & 0 deletions .storybook/stories/Examples/AnimationCloth/Info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';

const { PropTypes } = React;

class Info extends React.Component {
static propTypes = {
toggleWind: PropTypes.func.isRequired,
toggleSphere: PropTypes.func.isRequired,
togglePins: PropTypes.func.isRequired,
toggleRotate: PropTypes.func.isRequired,
onFrameChange: PropTypes.func.isRequired,
minTimePerFrame: PropTypes.number.isRequired,
rotating: PropTypes.bool.isRequired,
winding: PropTypes.bool.isRequired,
balling: PropTypes.bool.isRequired,
};

render() {
const linkStyle = {
textDecoration: 'underline',
cursor: 'pointer',
};

const {
toggleRotate,
toggleWind,
toggleSphere,
togglePins,
minTimePerFrame,
onFrameChange,
rotating,
winding,
balling,
} = this.props;

return (<div
style={{
textAlign: 'center',
padding: 10,
zIndex: 10,
width: '100%',
position: 'absolute',
color: '#000',
}}
>
<a
href="http://threejs.org"
style={{
color: '#0080ff',
}}
>three.js</a> - Simple Cloth Simulation<br/>
Verlet integration with Constrains relaxation<br/>
Toggle: <a onClick={toggleRotate} style={linkStyle}>Camera{rotating ? '*' : null}</a> |
<span> <a onClick={toggleWind} style={linkStyle}>Wind{winding ? '*' : null}</a></span> |
<span> <a onClick={toggleSphere} style={linkStyle}>Ball{balling ? '*' : null}</a></span> |
<span> <a onClick={togglePins} style={linkStyle}>Pins</a></span> |
<span> Time between frames (ms): <input
onChange={onFrameChange}
value={minTimePerFrame}
type="number"
style={{ width: 40 }}
min="0"
/> </span>
<br/>
<span>Note: add some time between frames (e.g. 60ms)
if you would like to inspect the scene through
react devtools, because updating every frame kills the addon.</span>
</div>);
}
}

export default Info;
Loading