LineDashedMaterial - keep dashes the same length when changing line length - three.js

I have a created a dashed line which changes position and length over time. To update it's position I'm adjusting the vertices of it's geometry object. This works great, except when the line becomes longer or shorter the dashes also get longer or shorter, despite being defined in absolute units, not relative to the length of the line.
I am already calling geometry.computeLineDistances() on initialisation (I have to do this to get the dashing to work at all), and I expected that if I simply called this in every render loop they would keep to the right scale, but that doesn't work.
Is there anything I can do to keep the dashes fixed length as the line changes length?
Here is a jsfiddle that illustrates the problem (code below): https://jsfiddle.net/fyr519L8/
var camera, scene, renderer, geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 30, 0);
camera.lookAt(scene.position);
scene.add(camera);
geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 0, 15));
geometry.computeLineDistances();
material = new THREE.LineDashedMaterial({
color: 0x000000,
dashSize: 1,
gapSize: 1,
linewidth: 1
});
mesh = new THREE.Line(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
geometry.vertices[0].z = Math.sin(Date.now() / 1000) * 10;
geometry.verticesNeedUpdate = true;
renderer.render(scene, camera);
}

If I got you right, then you can do this:
function render() {
geometry.vertices[0].z = Math.sin(Date.now() / 1000) * 10;
geometry.verticesNeedUpdate = true;
geometry.computeLineDistances(); // re-calculate line distances
geometry.lineDistancesNeedUpdate = true;
renderer.render(scene, camera);
}
UPD#1 Method .computeLineDistances() has been moved from THREE.Geometry() to THREE.Line() (r94)

Related

How to create tubes efficiently in three.js

I'm struggling to make tubes in THREE.js and there are very few tutorials on them so I decided to ask here. How can I create a tube without using this difficult piece of code taken from the official docs?
class CustomSinCurve extends THREE.Curve {
constructor( scale = 1 ) {
super();
this.scale = scale;
}
getPoint( t, optionalTarget = new THREE.Vector3() ) {
const tx = t * 3 - 1.5;
const ty = Math.sin( 2 * Math.PI * t );
const tz = 0;
return optionalTarget.set( tx, ty, tz ).multiplyScalar( this.scale );
}
}
Preferably with the use of bezier curves or something intuitive.
(To be clear, I'm using React-three-fiber to create these models but I know how to convert vanilla THREE.js to it.)
Try it like so:
let mesh;
let camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 4;
scene = new THREE.Scene();
const curve = new THREE.QuadraticBezierCurve3(new THREE.Vector3(-1, -1, 0), new THREE.Vector3(-1, 1, 0), new THREE.Vector3(1, 1, 0))
const geometry = new THREE.TubeGeometry(curve);
const material = new THREE.MeshNormalMaterial({
side: THREE.DoubleSide
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.133.1/build/three.min.js"></script>
The example code uses a simple quadratic bezier curve in order to generate the tube's shape.

Bringing back the object to the starting position

Here I'm trying to bring back the object to the starting position in the button click. I tried with some fixing the position of the object with the static position where I have no idea where it works or not. I have searched for solutions where they say to move the camera to FOV direction axis(say calculating the x, y, z).
In detail, if I pan or rotate aa object from initial position to different position, in button click I have to undo it to the the start position.
Here's the https://jsfiddle.net/Ajay_Venkatesh/thpb8csv/1/
'use strict';
var camera, scene, renderer;
var cube, cube_geometry, cube_material;
var controls;
init();
render();
function init() {
scene = new THREE.Scene();
// renderer
renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 12;
// controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);
controls.enableZoom = false;
// mesh - cube
cube_geometry = new THREE.CubeGeometry(5, 5, 5);
for (var i = 0; i < cube_geometry.faces.length; i += 2) {
var color = Math.random() * 0xffffff;
cube_geometry.faces[i].color.setHex(color);
cube_geometry.faces[i + 1].color.setHex(color);
}
cube_material = new THREE.MeshLambertMaterial({
color: 0xffffff,
vertexColors: THREE.FaceColors
});
cube = new THREE.Mesh(cube_geometry, cube_material);
scene.add(cube);
// Lights
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
var light = new THREE.DirectionalLight(0x002288);
light.position.set(-1, -1, -1);
scene.add(light);
var light = new THREE.AmbientLight(0x222222);
scene.add(light);
// events
window.addEventListener('resize', onWindowResize, false);
}
function render() {
renderer.render(scene, camera);
}
function onWindowResize(event) {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}

Detecting object collision by dragging. Trying to use the raycaster intersectObjects method

I am simply trying to detect when the lower sphere (the draggable one) is intersecting with the upper ones. I'm sure there's something I do not understand, unfortunately, nothing is crossing my mind on what.
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = drawSphere(); sphere2.position.set(15, 23, 0);
sphere3 = drawSphere(); sphere3.position.set(0, 22, 0);
sphere4 = drawSphere(); sphere4.position.set(-20, 20, 0);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Pixel coordinates
mouse.x = event.clientX;
mouse.y = event.clientY;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(sphere1, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
};
</script>
The only thing I can think of is my usage of the intersectObjects() method or the setFromCamera(), but I am not sure. I think this would make sense, since it is updated on mouse move. How would I say: "I want the draggable sphere to be the raycaster, as I move it, and detect collision"? Or something simpler to detect when things collide.
For instance, consider the following:
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
console.log(raycaster);
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(mouse, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
console.log('Hit on: ', intersects[i].object.uuid);
}
};
In this example, the raycaster is the mouse. You'll see the 'hit' message on the console, every time there is a mouse hover the spheres I've specified in the intersectObjects() method.
if you aren't casting a ray from the mouse cursor, you don't need .setFromCamera().. you would just set up the ray manually.
You can use raycasting to check if one sphere hits another, or you can do a sphere->sphere intersection test like this..
var tmp = new THREE.Vector3();
function spheresCollide(centerA,radiusA,centerB,radiusB){
var sqdist = radiusA+radiusB;
sqdist*=sqdist;
tmp.copy(centerB).sub(centerA)
if(tmp.lengthSq()<sqdist)return true;
return false;
}
//centerA and centerB are the vector3 positions of your spheres.. radiusA and B are the sphere radii
To do a raycast, you'll need to do something like the following, for each sphere:
rayCaster.ray.origin.copy(sphereA.position);
rayCaster.ray.direction.copy(sphereB.position).sub(sphereA.position).normalize()
intersects = raycaster.intersectObjects([sphereB]);
for(var i = 0; i < intersects.length; i++){
tmp.copy(intersects[i].position).sub(sphereA.position);
if(tmp.length()<(radiusA+radiusB)){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
}
It took me a while to get through this. There's something different about raycasting to a moving object. The idea behind ray casting is that a ray is being casted. For this example, the setFromCamera() method won't do, because the 'sphere' is supposed to be the object the ray(s) is(are) coming from.
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster,
scene, camera, sphere1, sphere2,
sphere3, sphere4, dragControls;
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
raycasting();
};
function eventful(){ // Where all events happen
dragControls = new THREE.DragControls([sphere1], camera, renderer.domElement);
dragControls.addEventListener('dragstart', onDragStart, false);
dragControls.addEventListener('dragend', onDragEnd, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.CubeGeometry(3,3,3,1,1,1);
material = new THREE.MeshBasicMaterial({
wireframe: true
});
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onDragStart(event){
console.log('on drag start');
};
function onDragEnd(event){
console.log('on drag end');
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
};
//////////////////////////////
//////// RAYCASTING //////////
//////////////////////////////
function raycasting(){ // Blast rays like Cyclops or Superman, but only to measure proximity
var sphere1Origin, // The 3D position of sphere1 when the page loads
vIndex, // Vertex index
sphere1VLength, // The amount of vertices
dVector, // The directions the ray should be pointing to while it is moving
raycaster, // The ray casting from a given point
sphere1Origin = getUpdatedPosition();
sphere1VLength = sphere1.geometry.vertices.length;
for(vIndex = 0; vIndex < sphere1VLength; vIndex++){
dVector = bindRaysToVertices(sphere1, vIndex);
raycaster = raycast(sphere1Origin, dVector);
collided = detectCollision(raycaster, dVector).hasCollided;
if(collided){
console.log('Hit!');
}
}
};
function detectCollision(raycaster, dVector){ // Determines whether there is/are (a) collision(s)
var collisions, // Results of each collisions
collided; // True/False
collisions = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
collided = collisions.length > 0 && collisions[0].distance < dVector.length();
return {
hasCollided: collided,
collisionsList: collisions
};
};
function bindRaysToVertices(sphere1, vIndex){ // Make the geometry blast rays in all directions, while moving
var lVertex, // The re-calculated (updated) vertices for the moving object
gVertex, // The complete representation of the re-calculated (updated) vertices
dVector; // The directions the ray should be pointing to while it is moving
lVertex = sphere1.geometry.vertices[vIndex].clone();
gVertex = lVertex.applyMatrix4(sphere1.matrix);
dVector = gVertex.sub(sphere1.position);
return dVector;
};
function getUpdatedPosition(){
var sphere1Origin, // The 3D position of sphere1 when the page loads
sphere1Origin = sphere1.position.clone();
return sphere1Origin;
};
function raycast(sphere1Origin, dVector){
// Make the sphere cast the ray, through its vertices,
// while moving, using a Normalized Coordinate System
return new THREE.Raycaster(sphere1Origin, toNCS(dVector));
};
function toNCS(dVector){ // To Normalize Coordinate System
return dVector.clone().normalize();
};
</script>
Following Stemkoski example, I've decided to use cubes as wireframes, and should there be a need to have a sphere, the cube should be within it. Otherwise it will be computationally expensive to have a sphere blasting rays like the Sun for proximity detection purposes.

Three.js - How to slowly change the camera's orientation untill it reaches a specific vector

I'm using Three.js to develop a player for 360° pictures, and I need some advice.
I have created a few cliquable meshs inside the scene. Currently, when the user clicks on a mesh, the camera's orientation is brutally changed to the mesh's direction. (this done by calling THREE.Camera.lookat()).
What I want is that when the users clicks, the camera transitions smoothly from it's target vector to the mesh's direction. I would like that the camera takes about 1 second to go from its current vector to the mesh's direction.
I have seen that tween is a library with which we can animate the scene, but I didn't really understand how it works.
Do you know what I could use to implement this animation ?
If tween can help me, can you explain how tween comes into play with three.js, or can you link some githubs or else ?
Thank you for feedbacks.
Just an extension of the manthrax's idea with Tween.js
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10, 32, 24), new THREE.MeshBasicMaterial({
color: "yellow",
wireframe: true
}));
scene.add(sphere);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var startRotation = new THREE.Quaternion();
var targetRotation = new THREE.Quaternion();
window.addEventListener("mousedown", onMouseDown, false);
function onMouseDown(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
let newPosition = raycaster.ray.at(10);
setPoint(newPosition);
// manthrax's idea + Tween.js
startRotation.copy(camera.quaternion);
camera.lookAt(newPosition);
camera.updateMatrixWorld();
targetRotation = camera.quaternion.clone();
camera.quaternion.copy(startRotation);
new TWEEN.Tween(camera.quaternion).to(targetRotation, 1000).easing(TWEEN.Easing.Bounce.Out).delay(250).start();
// one of benefits of using Tween.js is easings
// you can find many of them here
// https://sole.github.io/tween.js/examples/03_graphs.html
}
function setPoint(position) {
let point = new THREE.Mesh(new THREE.SphereGeometry(0.125, 4, 2), new THREE.MeshBasicMaterial({
color: "red",
wireframe: true
}));
point.position.copy(position);
scene.add(point);
}
render()
function render() {
requestAnimationFrame(render);
TWEEN.update(); // don't forget to put this line into the animation loop, when you use Tween.js
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
Something like:
var targetRotation,startTime,transitionDuration;
var startRotation = camera.quaternion.clone();
function smoothTransition(newTarget){
startRotation.copy(camera.quaternion);
camera.lookAt(newTarget);
camera.updateMatrixWorld();
targetRotation = camera.rotation.clone();
startTime = performance.now();
transitionDuration = 1000;
}
In animate:
if(startRotation){
var playTime = (performance.now()-startTime)/transitionDuration;
if(playTime>1)playTime = 1;
Quaternion.slerp(startRotation,targetRotation,camera.rotation,playTime);
camera.updateMatrixWorld();
}

Object with a higher renderOrder being clipped by rotated element

A rotated object (cylinder in this case) cuts off objects (a triangle made by lines in this case) even though the renderOrder of the second object is higher. See this jsfiddle demo for the effect.
The triangle should be rendered completely on top of the cylinder but is cut off where the outside of the cylinder intersects with it. It's easier to understand what's happening when a texture is used, but jsfiddle is bad at using external images.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer({
antialias: true,
preserveDrawingBuffer: true
});
renderer.setClearColor(0x24132E, 1);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 0, 7);
camera.lookAt(scene.position)
scene.add(camera);
var geometry = new THREE.CylinderGeometry(1, 1, 100, 32, 1, true);
var material = new THREE.MeshBasicMaterial({
color: 0x0000ff
});
material.side = THREE.DoubleSide;
mesh = new THREE.Mesh(geometry, material);
mesh.rotation.x = Math.PI / 2;
scene.add(mesh);
var c = 3, // Side length of the triangle
a = c / 2,
b = Math.sqrt(c * c - a * a),
yOffset = -b / 3; // The vertical offset (if 0, triangle is on x axis)
// Draw the red triangle
var geo = new THREE.Geometry();
geo.vertices.push(
new THREE.Vector3(0, b + yOffset, 0),
new THREE.Vector3(-a, 0 + yOffset, 0),
new THREE.Vector3(a, 0 + yOffset, 0),
new THREE.Vector3(0, b + yOffset, 0)
);
var lineMaterial = new THREE.LineBasicMaterial({
color: 0xff0000,
linewidth: 5,
linejoin: "miter"
});
plane = new THREE.Line(geo, lineMaterial);
// Place it on top of the cylinder
plane.renderOrder = 2; // This should override any clipping, right?
scene.add(plane);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
Am I doing something wrong or is this a bug?
for the effect that you want use a second scene and render it onto the first one
function init(){
.....
renderer.autoClear = false;
scene.add(tube);
overlayScene.add(triangle);
.....
}
function render() {
renderer.clear();
renderer.render(scene, camera);
renderer.clearDepth();
renderer.render(overlayScene, camera);
}
renderOrder does not mean what you think it means, look at the implementation in WebGLRenderer
objects are sorted by the order, if it meant what you anticipated from it, there would always be some fixed rendering order and colliding objects would be seen through each other, renderOrder is AFAIK used when you have issues with order of transparent/ not opaque objects
I worte a little plugin for three.js for flares for my game. Three.js built-in flares plugin is slow and I preferred not to run another rendering pass which was cutting framerate in half. Here's how I got flares visible on top of objects which were actually in front of them.
Material parameters:
{
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true,
map: flareMap,
depthWrite: false,
polygonOffset: true,
polygonOffsetFactor: -200
}
depthWrite - set to false
polygonOffset - set to true
polygonOffsetFactor - give negative number to get object in front of others. Give it some really high value to be really on top of everything i.e. -10000
Ignore other params, they are needed for my flares

Resources