I'm trying to make the direction flow and air flow like this example: /
As I can see there's only the texture is moving
I don't understand how to make the air flowing to correct direction on the pipe and surface like that.
Any idea is much appreciated!
(I'm thinking they might use some uv unwrap technique bine with animate the UV offset of texture)
I'm trying to make the direction flow and air flow like this example: https://animagraffs./supercharger-vs-turbo/
As I can see there's only the texture is moving
I don't understand how to make the air flowing to correct direction on the pipe and surface like that.
Any idea is much appreciated!
(I'm thinking they might use some uv unwrap technique bine with animate the UV offset of texture)
Share Improve this question edited Apr 16, 2017 at 3:19 user128511 asked Apr 15, 2017 at 23:32 Ben MackBen Mack 4992 gold badges7 silver badges32 bronze badges1 Answer
Reset to default 10It looks like you can just adjust a texture's UV offset
texture.offset.x = someAnimatedValue;
texture.offset.y = someAnimatedValue;
As for making the pipe itself, pretty much any 3d modeling package (blender, maya, 3d studio max, etc...) will let you extrude a line along a path. So to make the pipe you make a circle and then extrude it along the path. Similarly you can put a wall/fence down the center of a pipe by extruding a line down the same curve. The default UV coordinates will be correct for scrolling.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
// make a texture with an arrow
const ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = 64;
ctx.canvas.height = 64;
ctx.fillStyle = "rgba(0,0,255,0.5)";
ctx.fillRect(0, 0, 64, 64);
ctx.translate(32, 32);
ctx.rotate(Math.PI * .5);
ctx.fillStyle = "rgb(0,255,255)";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "48px sans-serif";
ctx.fillText("➡︎", 0, 0);
const texture = new THREE.CanvasTexture(ctx.canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.x = 4;
texture.repeat.y = 9;
const radiusTop = 1;
const radiusBottom = 1;
const height = 5;
const radiusSegments = 20;
const heightSegments = 2;
const openEnded = true;
const geometry = new THREE.CylinderBufferGeometry(
radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded);
const material = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide,
depthWrite: false,
depthTest: false,
transparent: true,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
mesh.rotation.z = Math.PI * .5;
function render(time) {
time *= 0.001;
resize();
const cameraSpeed = time * 0.3;
const cameraRadius = 5;
camera.position.x = Math.cos(cameraSpeed) * cameraRadius;
camera.position.y = 1;
camera.position.z = Math.sin(cameraSpeed) * cameraRadius;
camera.lookAt(mesh.position);
texture.offset.y = (time * 3 % 1);
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://cdnjs.cloudflare./ajax/libs/three.js/84/three.min.js"></script>
Note that looking at the original diagram I'd stay they aren't animating a pipe, they are animating a strip that's inside the pipe at has an arrow texture being scrolled on it. So, in you modeling package, after creating the pipes extrude a line down the path.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
// make a texture with an arrow
const ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = 64;
ctx.canvas.height = 64;
ctx.translate(32, 32);
ctx.rotate(Math.PI * .5);
ctx.fillStyle = "rgb(0,255,255)";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "48px sans-serif";
ctx.fillText("➡︎", 0, 0);
const texture = new THREE.CanvasTexture(ctx.canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.x = 1;
texture.repeat.y = 5;
const radiusTop = 1;
const radiusBottom = 1;
const height = 5;
const radiusSegments = 20;
const heightSegments = 2;
const openEnded = true;
const geometry = new THREE.CylinderBufferGeometry(
radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded);
const material = new THREE.MeshBasicMaterial({
color: 0x4040FF,
opacity: 0.5,
side: THREE.DoubleSide,
depthWrite: false,
depthTest: false,
transparent: true,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
mesh.rotation.z = Math.PI * .5;
const stripGeo = new THREE.PlaneBufferGeometry(radiusTop * 1.7, height);
const stripMat = new THREE.MeshBasicMaterial({
map: texture,
opacity: 0.5,
side: THREE.DoubleSide,
depthWrite: false,
depthTest: false,
transparent: true,
});
const stripMesh = new THREE.Mesh(stripGeo, stripMat);
scene.add(stripMesh);
stripMesh.rotation.z = Math.PI * .5;
function render(time) {
time *= 0.001;
resize();
const cameraSpeed = time * 0.3;
const cameraRadius = 5;
camera.position.x = Math.cos(cameraSpeed) * cameraRadius;
camera.position.y = 1;
camera.position.z = Math.sin(cameraSpeed) * cameraRadius;
camera.lookAt(mesh.position);
texture.offset.y = (time * 3 % 1);
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
function resize() {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
if (canvas.width !== width || canvas.height !== height) {
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://cdnjs.cloudflare./ajax/libs/three.js/84/three.min.js"></script>
PS: I'm too lazy to deal with the sorting issues but dealing with that should be a separate quesiton