ThreeJS translate center of Object3D to it's actual center - three.js

I have an Object3D containting multiple Cubes which represent a grid. However when I move my camera (OrbitControls) the view dosn't rotate around the center of my grid but rather the center of my initial view.
function createGrid(x, y) {
const field = new THREE.Object3D()
for(let col = 0; col < x; col++){
for (let row = 0; row < y; row++) {
let cube = createCube()
cube.position.x = col
cube.position.z = row
field.add(cube)
}
}
return field
}
The createCube() function creats a simple cube (size 1 for all dimensions) and sets some default values (Material, Color). filed is then appended to the scene via scene.add(createGrid(10, 10)).
Now, how can I translate my "center" to the actual center of the Object3D element?
I'm new to Three.js and WebGL in general. Any advice is appreciated.

Related

TileMap color is changing depending on Camera angle [UNITY]

Currently, I'm trying to highlight tiles around the outside of the object currently being dragged. I have tilemaps attached to the same object, one is the white border around the outside of the object and the other is the green center. The issue I am having at the moment is when the camera is facing the tiles at a set angle, the green tile will seem pale and at some coordinates. However, if I move the rotation or position of the camera, the pale tile will turn back to a solid green but turn pale again at another coordinate. I've attached two photos to show an example.
And here is the code involved with the tilemap:
//Reinitialize position to match TileMap orientation;
Vector3 newVec = new Vector3(pos.x, pos.z, 0);
Vector3 bottomRightPoint = newVec + new Vector3(1, 1, 0);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
//if tile painting is the center player tile
if (i == 1 && j == 1) {
colourTileMap.color = selfTile;
colourTileMap.SetTile(Vector3Int.FloorToInt(bottomRightPoint - new Vector3(i, j, 0)), tile);
Debug.Log("selfTile" + selfTile);
}
tileMap.SetTile(Vector3Int.FloorToInt(bottomRightPoint - new Vector3(i, j, 0)), tile);
}
}
}
If you need any other information please feel free to reach out. Thanks in advance!

How to calculate the area of merged plane in ThreeJS

image
get the area of merged planes
I can get area of each plane, but planes overlapped with each other, I can get a area of them all, but it's not what I want, the overlapped areas should excluded.
var geom = plane.geometry;
var area = 0;
for (var i = 0; i < geom.faces.length; i++) {
var face = geom.faces[i];
var tri = new THREE.Triangle(geom.vertices[face.a], geom.vertices[face.b], geom.vertices[face.c]);
var area = area + tri.getArea();
}
console.log(area);
There should be a method to calculate the area.
THREE.ShapeUtils.area( contour) gives a negative result.
If you want to highlight the edges of your geometry, you can use EdgesHelper:
var helper = new THREE.EdgesHelper( mesh, 0x00ffff );
helper.material.linewidth = 2;
scene.add( helper )
and get contour from Edges helper if required

Three.js, center camera to view all objects that is in the scene

I write an algorithm that can explode (fold and unfold) mechanical set by double clicking on then.
But i want to move the camera backward or forward after that to see all my objects in the fov.
I'm trying to use frustum to calculate intersection between frustum and objects, but i don't undestand how to use planes.
I'm working with OrthographicCamera.
What i do :
At every frame i recalculate the new frustum (when camera move):
projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
frustum.setFromMatrix(projScreenMatrix);
Then i do a loop over the 6 planes and bounding box of all objects in the scene :
for (var i = 0; i < planes.length; i++) {
var plane = planes[i];
for (var j = 0; j < boxs.length; j++) {
var box = boxs[j];
var line = new THREE.Line3(box.min, nox.max);
//console.log({'plane': plane, 'line': line});
if (plane.isIntersectionLine(line))
// move camera
};
};
but plane.isIntersectionLine(line) is always false.
Do you have any ideas ?
Thanks

Emgu CV draw rotated rectangle

I'm looking for few days a solution to draw rectangle on image frame. Basically I'm using CvInvoke.cvRectangle method to draw rectangle on image because I need antialiased rect.
But problem is when I need to rotate a given shape for given angle. I can't find any good solution.
I have tryed to draw rectangle on separate frame then rotate hole frame and apply this new image on top of my base frame. But in this solution there is a problem with antialiasing. It's not working.
I'm working on simple application that should allow draw few kinds of shape, resize them and rotation for given angle.
Any idea how to achive this?
The best way I found to draw a minimum enclosing rectangle on the contour is using the Polylines() function which uses vertices that are returned from MinAreaRect() function. There are surely other ways to do it as well. Here is the code walk down:
// Find contours
var contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(image, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);
// According to your metric, get an index of the contour you want to find the min enclosing rectangle for
int index = 2; // Say, 2nd index works for you.
var rectangle = CvInvoke.MinAreaRect(contours[index]);
Point[] vertices = Array.ConvertAll(rectangle.GetVertices(), Point.Round);
CvInvoke.Polylines(image, vertices, true, new MCvScalar(0, 0, 255), 5);
The result can be visualized in the image below, in red is the minimum enclosing rectangle.
I use C# and EMGU.CV(4.1), and I think this code will not be difficult to transfer to any platform.
Add function in the in your helper:
public static Mat DrawRect(Mat input, RotatedRect rect, MCvScalar color = default(MCvScalar),
int thickness = 1, LineType lineType = LineType.EightConnected, int shift = 0)
{
var v = rect.GetVertices();
var prevPoint = v[0];
var firstPoint = prevPoint;
var nextPoint = prevPoint;
var lastPoint = nextPoint;
for (var i = 1; i < v.Length; i++)
{
nextPoint = v[i];
CvInvoke.Line(input, Point.Round(prevPoint), Point.Round(nextPoint), color, thickness, lineType, shift);
prevPoint = nextPoint;
lastPoint = prevPoint;
}
CvInvoke.Line(input, Point.Round(lastPoint), Point.Round(firstPoint), color, thickness, lineType, shift);
return input;
}
This draws roteted rectangle by points. Here used rounding points by method Point.Round becose RotatedRect has points in float coordinates and CvInvoke.Line takes points as integer.
Use:
var mat = Mat.Zeros(200, 200, DepthType.Cv8U, 3);
mat.GetValueRange();
var rRect = new RotatedRect(new PointF(100, 100), new SizeF(100, 50), 30);
DrawRect(mat, rRect,new MCvScalar(255,0,0));
var brect = CvInvoke.BoundingRectangle(new VectorOfPointF(rRect.GetVertices()));
CvInvoke.Rectangle(mat, brect, new MCvScalar(0,255,0), 1, LineType.EightConnected, 0);
Result:
You should read the OpenCV documentation.
There is a RotatedRectangle class that you can use for your task. You can specify the angle by which the rectangle will be rotated.
Here is a sample code (taken from the docs) for drawing a rotated rectangle:
Mat image(200, 200, CV_8UC3, Scalar(0));
RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30);
Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));
Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));
imshow("rectangles", image);
waitKey(0);
Here is the result:

Three.js set the center of a Object3D based on internal meshes

I have a mesh set that is in a Object3D when i get the vertices they are not centered on the object. so i need to compute the center of the object3D then move the meshes to align them to the center. I have tried computing the boundingboxes of each Mesh then max - min /2; this does not work. Any help here would be fantastic. I have tried the Object3D.setFromObject(); this only return infinity.
To center an Object3D, depending on its children, you have to iterate through them, as far as I know. The code would look like the following:
// myObject3D is your Object3D
var children = myObject3D.children,
completeBoundingBox = new THREE.Box3(); // create a new box which will contain the entire values
for(var i = 0, j = children.length; i < j; i++){ // iterate through the children
children[i].geometry.computeBoundingBox(); // compute the bounding box of the the meshes geometry
var box = children[i].geometry.boundingBox.clone(); // clone the calculated bounding box, because we have to translate it
box.translate(children[i].position); // translate the geometries bounding box by the meshes position
completeBoundingBox.addPoint(box.max).addPoint(box.min); // add the max and min values to your completeBoundingBox
}
var objectCenter = completeBoundingBox.center()
console.log('This is the center of your Object3D:', objectCenter );
// You want the center of you bounding box to be at 0|0|0
myObject3D.position.x -= objectCenter.x;
myObject3D.position.y -= objectCenter.y;
myObject3D.position.z -= objectCenter.z;
Hope I understood your problem right!
center = function(obj) {
var children = obj.children,
completeBoundingBox = new THREE.Box3();
for(var i = 0, j = children.length; i < j; i++) {
children[i].geometry.computeBoundingBox();
var box = children[i].geometry.boundingBox.clone();
box.translate(children[i].position);
completeBoundingBox.set(box.max, box.min);
}
var objectCenter = completeBoundingBox.center()
console.log('This is the center of your Object3D:', objectCenter );
obj.position.x -= objectCenter.x;
obj.position.y -= objectCenter.y;
obj.position.z -= objectCenter.z;
}

Resources