# 2D object in 3D space (by Vertices)

2 Likes

Thanks. It was my question on stackoverflow

Yeah, I see
Just in case: https://jsfiddle.net/prisoner849/gnp5ktjh/

2 Likes

As always an elegant solution.

I once tested some variants.

It seems that the method also works with non-complanar points.
Only uv’s missing

It seems that non-complanar points also work. Only uv’s missing!

1 Like

@hofk
Thanks for testing

Kind of a related topic:

I was sure that it won’t last so simple, and there was evolving:

2 Likes

Hi,
I have following code now:

``````function addObject3D( Object )
{
var AllFaces = new THREE.Group();
for(var f=0; f < Object.Faces.length; f++)
{
var points = [];
Object.Faces[f].Vertices3D.forEach(r => {
points.push(new THREE.Vector3(r.x, r.y, r.z));
});

var tri = new THREE.Triangle(points[2], points[1], points[0]);
var normal = new THREE.Vector3();
tri.getNormal(normal);

var baseNormal = new THREE.Vector3(0, 0, 1);
var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, baseNormal);

var tempPoints = [];
points.forEach(p => {
tempPoints.push(p.clone().applyQuaternion(quaternion));
})

var shape = new THREE.Shape(tempPoints);
var shapeGeom = new THREE.ShapeGeometry(shape);

var Material = new THREE.MeshBasicMaterial( { map: Texture } );
Material.side = THREE.DoubleSide;

var mesh = new THREE.Mesh( shapeGeom, Material ) ;

mesh.geometry.vertices = points;

}

return AllFaces;
}
``````

Everything is ok, when I use THREE.MeshBasicMaterial, but when i try to use a texture - the object has a solid color instead the texture.
How to use the texture?

1 Like

Possibly, there’s something wrong with UV coordinates.

Also I think threejs is incompatible with php

My mistake.
There is no `<?php` line

@prisoner849 Tinkering a bit with your code, I have found one issue.

In this example, I draw a polygon in the X-Y (horizontal) plane, and then project the points into a tilted plane so that all points’ Z coordinates are non-negative. The resulting face/plane is not drawn as expected (i.e.: the contour “jumps” between non-contiguous points in the perimeter):

https://jsfiddle.net/Peque/0tj2vceg

The expected result should be an L-shaped polygon with just 6 segments between each contiguous pair of vertices and with all the area within the projected polygon filled.

Any ideas on what is happening or how could I fix that?

Might be a problem of accuracy

I cleaned up the code a bit.

``````<head>
<title> planetest </title>
<meta charset="utf-8" />

<body> </body>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

<script>
var renderer, controls, scene, camera;

init();

function init() {

// Scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xb0b0b0);

// Camera
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 400);
camera.up.set(0, 0, 1);

// Light
var ambientLight = new THREE.AmbientLight(0xcccccc, 0.2);

// Helpers
var helpers = new THREE.Group();
var grid = new THREE.GridHelper(200, 10);
grid.rotation.x = Math.PI / 2;
var axis = THREE.AxisHelper(100);

// Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Controls
controls = new THREE.OrbitControls(camera, renderer.domElement);

// Event listeners

// Draw projected mesh
var points = [

new THREE.Vector2(-20, 0),
new THREE.Vector2(-20, -20),
new THREE.Vector2(20, -20),
new THREE.Vector2(20, 20),
new THREE.Vector2(0, 20),

//new THREE.Vector2(0, 0),
new THREE.Vector2(-0.00000000001, 0.00000000001),

new THREE.Vector2(-20, 0),

];

var plane = new THREE.Plane().setFromNormalAndCoplanarPoint(

new THREE.Vector3(0.7071067811865475, 0, 0.7071067811865475),
new THREE.Vector3(20, 0, 0)

);

var mesh = projectPoints( points, plane );

// Render
render();
}

function projectPoints( points, plane ) {
var projectedPoints = [];
const upDirection = new THREE.Vector3(0, 0, 1);
points.forEach(p => {
const r = new THREE.Ray(new THREE.Vector3(p.x, p.y, 0.0), upDirection);
let intersection = new THREE.Vector3();
r.intersectPlane(plane, intersection);
projectedPoints.push(new THREE.Vector3(p.x, p.y, intersection.z));
});

var shape = new THREE.Shape(projectedPoints );
var shapeGeom = new THREE.ShapeGeometry(shape);
var mesh = new THREE.Mesh(
shapeGeom,
new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
wireframe: false,
transparent: true,
opacity: 0.3,
})
);
console.log(projectedPoints);
mesh.geometry.vertices = projectedPoints;
return mesh;

}

function render() {

renderer.render(scene, camera);

}
</script>
</html>``````
1 Like

As an option, try this approach without quaternions:
https://jsfiddle.net/prisoner849/gsLz4vmk/

1 Like

Thanks for having a look at it and for the refactoring!

Yeah, it seems it fails depending on the set of points used. But I have found it is not related to having a point at `(0, 0)`. So, for example…

This works:

``````var points = [
new THREE.Vector2(-20, 0),
new THREE.Vector2(-20, -20),
new THREE.Vector2(20, -20),
new THREE.Vector2(20, 40),
new THREE.Vector2(-10, 40),
new THREE.Vector2(-10.0, 0.0),
new THREE.Vector2(-20, 0),
];
``````

This does not:

``````var points = [
new THREE.Vector2(-20, 0),
new THREE.Vector2(-20, -20),
new THREE.Vector2(10, -20),
new THREE.Vector2(10, 40),
new THREE.Vector2(-10, 40),
new THREE.Vector2(-10.0, 0.0),
new THREE.Vector2(-20, 0),
];
``````

Notice the change in points `2` and `3`, where I only change their `x` attribute from `20` to `10`.

Thanks a lot!

It works great. Only I just discovered the order is important… (hence your `reverse()` call). The problem is that the points on the X-Y plane are provided and there is no guarantee they come sorted counterclockwise (they could be sorted clockwise). Any magic Three.js function to deal with that?

Interestingly, the order does not seem to matter for the orange vertices. Only the `ShapeBufferGeometry` is affected.

Take a look at this method: https://threejs.org/docs/index.html#api/en/extras/ShapeUtils.isClockwise

1 Like

Works perfectly, thanks!

The docs say `.isClockwise` but it seems it is written `.isClockWise` (aren’t the docs autogenerated?).

True. There’s a typo in the docs Must be `.isClockWise()`

or a typo in the source code

1 Like

@hofk Could it be a problem of the order of the vertices in the array? I tried with `points = points.reverse();` (got the idea from @prisoner849’s proposal) and it seems to work fine (?).

Not sure if it really works fine when you make sure points are sorted anticlockwise or it is just luck and simply, with enough time, I will find another example that fails.