Three. js рисует форму между Object3D и Sprite - PullRequest
1 голос
/ 16 февраля 2020

У меня есть вращающийся Object3D с прикрепленными к нему метками Sprite. Спрайты расположены правильно и вращаются вокруг Object3D, всегда обращенного к камере.

Мне нужно нарисовать хвосты стиля речевого пузыря на метках, чтобы они указывали назад на местоположение на Object3D. Это довольно просто с линией, но становится более сложным с формой.

enter image description here

  • Зеленый - это куб Object3D
  • Синий - это форма, которая нуждается в ее вращении. Y исправление
  • Белый - это метка спрайта

До сих пор у меня была синяя форма, размер и правильное расположение. Однако ось вращения y должна динамически обновляться относительно вращения Object3D и положения камеры. Я пробовал .lookAt (), но он не работает, поскольку он вращает все оси. Мне нужно повлиять только на вращение y.

Также вопрос, является ли это лучшим подходом в целом?

Спасибо!

// Scene setup
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var ambientLight = new THREE.AmbientLight(0xffffff, .5);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
var group = new THREE.Group();
scene.add(group);

// Cube
var cubeSize = 1;
var geometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
var material = new THREE.MeshLambertMaterial({
  color: 0x00ff00
});
var cube = new THREE.Mesh(geometry, material);
group.add(cube);

// Text label
var config = {
  fontface: 'Arial',
  fontsize: 64,
  fontweight: 500,
  lineheight: 1,
  padding: 20
};
var text = 'Hello world!';
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
const textMetrics = ctx.measureText(text);
var textWidth = textMetrics.width;
var textHeight = config.fontsize * config.lineheight;
canvas.width = textWidth + config.padding * 2;
canvas.height = textHeight + config.padding * 2;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, textWidth + config.padding * 2, textHeight + config.padding * 2);
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.font = `${config.fontweight} ${config.fontsize}px/${config.lineheight} ${config.fontface}`;
ctx.fillText(text, config.padding, config.padding);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var spriteMaterial = new THREE.SpriteMaterial({
  map: texture
});
var aspectRatio = spriteMaterial.map.image.height / spriteMaterial.map.image.width;
var sprite = new THREE.Sprite(spriteMaterial);
sprite.position.set(0, cubeSize * 2, 0);
sprite.scale.set(1, aspectRatio, 1);
group.add(sprite);

// ShapeGeometry Mesh
var arrowWidth = textHeight / 220;
var arrowHeight = sprite.position.y / 1.41;
var arrowShape = new THREE.Shape();
arrowShape.moveTo(0, 0);
arrowShape.lineTo(-arrowWidth / 2, arrowHeight);
arrowShape.lineTo(arrowWidth / 2, arrowHeight);
arrowShape.lineTo(0, 0);
var arrowGeometry = new THREE.ShapeGeometry(arrowShape);
var arrowMaterial = new THREE.MeshBasicMaterial({
  color: 0x0000ff,
  // depthWrite: false,
  side: THREE.DoubleSide
});
var arrow = new THREE.Mesh(arrowGeometry, arrowMaterial);
arrow.position.set(0, cubeSize / 2, 0);
/* arrow.up.copy(new THREE.Vector3(0, 1, 0)); */
group.add(arrow);

window.group = group;

var animate = function() {
  requestAnimationFrame(animate);

  group.rotation.x += 0.005;
  group.rotation.y += 0.005;
  group.rotation.z += 0.005;

  // Using lookAt with depthWrite:false almost works
  // arrow.lookAt(camera.position);
  // arrow.rotation.x = 0;
  // arrow.rotation.z = 0;

  renderer.render(scene, camera);
};

animate();
body {
  margin: 0;
}

canvas {
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
...