Help with trapezoidal reflector: bug or not?

Try to simulate the “holographic pyramid”.

I only build one trapezoidal plane (by feeding the required vertices of the geometry).
The floor is a BIG plane geometry with checkerboard texture.

[Please check the gif: https://i.imgur.com/DHMDeGE.gif]
The reflections look OK in some angles, but for some viewing angles, the result is clearly wrong (as shown below, since the floor is quite large, compared to the mirror.)
image

The code as
`
import * as THREE from ‘https://raw.githack.com/mrdoob/three.js/dev/build/three.module.js’;

import { OrbitControls } from 'https://raw.githack.com/mrdoob/three.js/dev/examples/jsm/controls/OrbitControls.js';
import { Reflector } from 'https://raw.githack.com/mrdoob/three.js/dev/examples/jsm/objects/Reflector.js';

var scene, renderer, camera;
var WIDTH, HEIGHT;

init();
animate();

function makeTrapezoid(l) {

  var geometry = new THREE.Geometry();
  geometry.vertices.push(
	new THREE.Vector3(0, 0, .5),
	new THREE.Vector3(l, 0, 3),
	new THREE.Vector3(l, 0, -3),
	new THREE.Vector3(0, 0, -.5)
  );

  var face;
  //face = new THREE.Face3(0, 1, 3);
  face = new THREE.Face3(0, 3, 1);

  face.materialIndex = 0;
  geometry.faces.push(face);
  //face = new THREE.Face3(1, 2, 3);
  face = new THREE.Face3(1, 3, 2);
  face.materialIndex = 0;
  geometry.faces.push(face);

  var verticalMirror = new Reflector( geometry, 
     {
					clipBias: 0.003,
					textureWidth: WIDTH * window.devicePixelRatio,
					textureHeight: HEIGHT * window.devicePixelRatio,
					color: 0x999999,
					recursion: 1
	 } );
 return verticalMirror;
 
}

function init() {
  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer();
   WIDTH = window.innerWidth;
   HEIGHT = window.innerHeight;
  renderer.setSize(WIDTH, HEIGHT);
  renderer.setClearColor(0x888888);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 3000);
  camera.position.z = 50;

  let controls = new OrbitControls(camera, renderer.domElement);

  window.addEventListener('resize', onWindowResize, false);
  scene.add (new THREE.AxesHelper(10));

var l = Math.sqrt (4.5 *4.5 - 2.5* 2.5);
var theta = Math.acos (2.5/l);
var trape;

trape = makeTrapezoid (l)
scene.add( trape);
trape.position.set (.5,0,0)
trape.rotation.z = theta;

let loader = new THREE.TextureLoader();
let tex  = loader.load ("https://i.imgur.com/p8CRm9W.jpg");
tex.repeat.set (10,10);
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;

  let floor = new THREE.Mesh (new THREE.PlaneGeometry (100,100), 
  	new THREE.MeshBasicMaterial({map: tex}));
  floor.rotation.x = -Math.PI/2;
  scene.add (floor);

}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
  
}

`

Three.js version
  • [x ] Dev
  • r106
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • [ x] macOS
  • Linux
  • Android
  • iOS

When reading your code I’ve noticed that you are not generating any uv-coordinates for your trapezoid. Hence, the mirror texture is probably not projected correctly onto the geometry.

Good point.

as this is a non-rectangular quad, may be I should be using STQ texture coordinates?!
Then the texture mapping would involve GLSL …
(as in http://jsfiddle.net/jmcjc5u/r9xwntuq/)

Does it still work with Reflector?

I don’t know. The mirror texture might look stretched. I guess you have to give it try and see how it goes.

I add the texture coordinates, simplify the geometry, and after further investigation, here are my findings.

  1. Not the issue of non-rectangular quad. The same thing happened for a rectangular quad, with correct texture coordinates.
  2. Compared with the “plane-geometry-ed” reflector, the images look quite different.

The program runs like this (https://i.imgur.com/cIprU8D.gifv) A “switch” can toggle between self-made quad and the threejs plane geometry, exactly the same size and orientation.

The test program can be found here:

I don’t know what else I can do … Please help.

Defining the trapezoid in the XY plane seems to solve the issue. Try it with this version of makeTrapezoid2().

function makeTrapezoid2( l ) {

	var geometry = new THREE.Geometry();
	geometry.vertices.push(
		new THREE.Vector3( - 3, l, 0 ),
		new THREE.Vector3( 3, l, 0 ),
		new THREE.Vector3( - 3, - l, 0 ),
		new THREE.Vector3( 3, - l, 0 )
	);

	var face;
	face = new THREE.Face3( 0, 2, 1 );
	face.materialIndex = 0;
	geometry.faces.push( face );

	face = new THREE.Face3( 2, 3, 1 );
	face.materialIndex = 0;
	geometry.faces.push( face );

	geometry.faceVertexUvs[ 0 ].push( [ new THREE.Vector2( 0, 1 ), new THREE.Vector2( 0, 0 ), new THREE.Vector2( 1, 1 ) ] );
	geometry.faceVertexUvs[ 0 ].push( [ new THREE.Vector2( 0, 0 ), new THREE.Vector2( 1, 0 ), new THREE.Vector2( 1, 1 ) ] );

	geometry.computeVertexNormals();

	var verticalMirror = new Reflector( geometry,
		{
			clipBias: 0.003,
			textureWidth: WIDTH * window.devicePixelRatio,
			textureHeight: HEIGHT * window.devicePixelRatio,
			color: 0x999999,
			recursion: 3
	 } );

	let group0 = new THREE.Object3D();
	group0.add( verticalMirror );
	verticalMirror.position.set( 0, l / 2, 0 );
	var group = new THREE.Object3D();
	group.add( group0 );

	group0.rotation.x = Math.PI / 2;
	group0.rotation.z = - Math.PI / 2;
	return group;

}