Discovering threejs since one month with an Oculus. Wow. WOW. Seem’s i found a really great toy for the rest of my addict dev life.
I already made some basic stuff successfully. I’m learning three, i dev vanillia js since a long time. I found a lot of answers in discourse, google, doc …
I’m using the dev branch of threejs (because i’d like to understand how gui.dat in vr mode is working without a raytracer )
My question is :
how to draw a simple plane (or rectangle) curved, like a curved screen ? (the texture may be a canvas or a video or a webcam stream)
I found some code playing with vertices, but probably because of the three version i’m using,
planegeometry don’t provide vertices array attributes. I didn’t test with previous version. The texture part with video is ok, just wondering how can i curve this plane like a curved TV
function planeCurve(g, z){
let p = g.parameters;
let hw = p.width * 0.5;
let a = new THREE.Vector2(-hw, 0);
let b = new THREE.Vector2(0, z);
let c = new THREE.Vector2(hw, 0);
let ab = new THREE.Vector2().subVectors(a, b);
let bc = new THREE.Vector2().subVectors(b, c);
let ac = new THREE.Vector2().subVectors(a, c);
let r = (ab.length() * bc.length() * ac.length()) / (2 * Math.abs(ab.cross(ac)));
let center = new THREE.Vector2(0, z - r);
let baseV = new THREE.Vector2().subVectors(a, center);
let baseAngle = baseV.angle() - (Math.PI * 0.5);
let arc = baseAngle * 2;
let uv = g.attributes.uv;
let pos = g.attributes.position;
let mainV = new THREE.Vector2();
for (let i = 0; i < uv.count; i++){
let uvRatio = 1 - uv.getX(i);
let y = pos.getY(i);
mainV.copy(c).rotateAround(center, (arc * uvRatio));
pos.setXYZ(i, mainV.x, y, -mainV.y);
}
pos.needsUpdate = true;
}
I took your code and i’ve put a link on this page. Very interesting for learning purpose, thank you !
So. My next step is to project multiple curved rectangles aligned horizontaly but following a cylinder geometry, with 8 rectangles max per horizontal, 4 horizontal max, 32 participants max. Starting point here (sphere geometry, for learning) : Planes on Sphere
No serious goal, pure experiences. Investigating/learning three, xr, oculus. The possibilities make me crazy. Challenging myself (math …)
Currently it’s seem’s that i’m about to code something like 3D UI, video conf room. Then, transform it into sandbox to play with immersive mode and keyboard/mouse behavior. No man’s sky demystification using threejs, sound nice !
Hey,
I’m using your planed curve code and it works pretty well! I have problems understanding the math though, would you be able to summarize what each section of the code does?
I did some research and found out the following (added comments to the sections):
function planeCurve(planeGeometry ,z){
let p = planeGeometry.parameters;
let hw = p.width * 0.5;
//Here three points are defined, the left edge, right edge and the z bend in y direction.
//These three points touch the circle with radius r at its border.
let a = new THREE.Vector2(-hw,0);
let b = new THREE.Vector2(0,z);
let c = new THREE.Vector2(hw,0);
let ab = new THREE.Vector2().subVectors(a,b);
let bc = new THREE.Vector2().subVectors(b,c);
let ac = new THREE.Vector2().subVectors(a,c);
//formula for finding a circle which contains all points on its edge.
let r = (ab.length() * bc.length() * ac.length()) / (2 * Math.abs(ab.cross(ac)));
//Calculation of the center of the circle. The center of the circle has to be at z - r, because r is the radius of the circle and b is positioned on the edge of the circle with (0,z)
let center = new THREE.Vector2(0, z - r);
//Generates a vector from the central point to the point to the left bottom.
let baseV = new THREE.Vector2().subVectors(a, center);
//And this is where i fail to get your code... Why these calculations?
let baseAngle = baseV.angle() - (Math.PI * 0.5);
let arc = baseAngle * 2;
let uv = planeGeometry.attributes.uv;
let pos = planeGeometry.attributes.position;
let mainV = new THREE.Vector2();
for(let i = 0; i < uv.count; i++){
//Why the 1 - uv.getX(i)? I don't understand it.
let uvRatio = 1 - uv.getX(i);
let y = pos.getY(i);
mainV.copy(c).rotateAround(center, (arc * uvRatio));
pos.setXYZ(i, mainV.x, y, -mainV.y);
}
pos.needsUpdate = true;
return planeGeometry;
}
I created a geogebra link for this to represent it more visually for me: Calculator Suite - GeoGebra
But i don’t understand what the calculations or the angle in general do? The angle alpha is equivalent to your baseV in the code, whereas your angle beta is equivalent to arc. Would be glad for any explanations regarding this!
Hi @prisoner849, can I ask how can I implemented this in R3F ? I check it other way but I couldn’t apply it. I was imaging it was the same as in R3F.
I image it something like this but I couldn’t imagine it if it was to pass in the planeGeometry, and also I wanna use other random images like a scenery image in the map is that also possible?
here is the code.
const PlaneGeometryImage = () => {
const plane = useMemo(() => {
function planeCurve(
g: { parameters: any; attributes: { uv: any; position: any; }; },
z: number
){
let p = g.parameters;
let hw = p.width * 0.5;
let a = new THREE.Vector2(-hw, 0);
let b = new THREE.Vector2(0, z);
let c = new THREE.Vector2(hw, 0);
let ab = new THREE.Vector2().subVectors(a, b);
let bc = new THREE.Vector2().subVectors(b, c);
let ac = new THREE.Vector2().subVectors(a, c);
let r = (ab.length() * bc.length() * ac.length()) / (2 * Math.abs(ab.cross(ac)));
let center = new THREE.Vector2(0, z - r);
let baseV = new THREE.Vector2().subVectors(a, center);
let baseAngle = baseV.angle() - (Math.PI * 0.5);
let arc = baseAngle * 2;
let uv = g.attributes.uv;
let pos = g.attributes.position;
let mainV = new THREE.Vector2();
for (let i = 0; i < uv.count; i++){
let uvRatio = 1 - uv.getX(i);
let y = pos.getY(i);
mainV.copy(c).rotateAround(center, (arc * uvRatio));
pos.setXYZ(i, mainV.x, y, -mainV.y);
}
pos.needsUpdate = true;
}
return planeCurve
},[])
return (<>
<mesh>
<planeGeometry
// how I will pass it here?
// and If it I will pass it here can how I add the
// image on it?
></planeGeometry>
<meshBasicMaterial
wireframe={true}
/>
</mesh>
</>)
}
Thanks for the post - very helpful. I also wanted a convex version and found that adding a negative z did not seem to do it with the @prisoner849 version. So what I did was added a few changes:
// at the top in the function
const negative = z<0;
z = Math.abs(z);
// down below in the function
pos.setXYZ(i, mainV.x, y, negative?mainV.y:-mainV.y);