Raycast not hitting a scene child using Three.js with GMaps - javascript

Im trying to hit a pin scene child with a click in GMaps, using Three.js and threejs-overlay-view but I can't get the object clicked. Raycaster.intersectObjects only returns [].
Image of pin
Here's a snippet of the code, everything works fine except the intersection part.
(async () => {
const map = await initMap();
const mapDiv = map.getDiv();
const mousePosition = new Vector2();
const raycaster = new THREE.Raycaster();
const overlay = new ThreeJSOverlayView(mapOptions.center);
const scene = overlay.getScene();
overlay.setMap(map);
...
map.addListener('click', ev => {
const {domEvent} = ev;
const {left, top, width, height} = mapDiv.getBoundingClientRect();
const x = domEvent.clientX - left;
const y = domEvent.clientY - top;
mousePosition.x = 2 * (x / width) - 1;
mousePosition.y = 1 - 2 * (y / height);
// dont get nothing here...
raycaster.setFromCamera(mousePosition, overlay.camera);
const intersects = raycaster.intersectObjects(scene.children, true);
overlay.requestRedraw();
});
overlay.update = () => {
// ... and here
raycaster.setFromCamera(mousePosition, overlay.camera);
const intersects = raycaster.intersectObjects(scene.children, true);
...
overlay.requestRedraw();
};
})();
Glad if any help, Thanks!

Related

Rotate a polygon in here maps api

I am making a navigation program around a building, i am trying to rotate the polygons around the top right point as the origin. I have tried multiple equations, but nothing seems to work.
this is the code to display the polygons, i have commented out the code that rotates the polygons.
const scaleX = 0.000000114939702;
const scaleY = 0.000000152939702;
const originX = 53.4724642;
const originY = -2.2393615;
//usage:
readTextFile("result.json", function(text){
const data = JSON.parse(text);
for (const i in data) {
const list = [];
list.push(data[i].C1, data[i].C2, data[i].C3, data[i].C4);
for (const j in list) {
list[j][0] = (originX-list[j][0]*scaleX)
list[j][1] = (-(list[j][1]*scaleY)+originY)
}
var width = list[0][0] - list[1][0];
var height = list[0][1] - list[3][1];
var distanceToOriginX = originX-list[0][0]
var distanceToOriginY = originY-list[0][1]
//list[0][0] = originX - Math.sin(0.524)*distanceToOriginX+height
//list[0][1] = originY + Math.cos(0.524)*distanceToOriginY+width
addPolygonToMap(map, (list[0][0]), (list[0][1]), (list[1][0]), (list[1][1]), (list[2][0]), (list[2][1]), (list[3][0]), (list[3][1]), 'rgba(0, 0, 255, 1)')
}
}); ```
This is my solution, i had to re-calculate the scale and the calculations had to be done before the co-ordinates were converted into longitude and latitude.
const scaleX = 0.000000107;
const scaleY = 0.000000171;
const originX = 53.4724642;
const originY = -2.2393615;
function readFile(filename, floor, colour) {
readTextFile(filename, function(text){
const data = JSON.parse(text);
for (const i in data) {
const list = [];
list.push(data[i].C1, data[i].C2, data[i].C3, data[i].C4);
var angle = 0.484
for (const j in list) {
var distanceToOrigin = pythagorean(list[j][1], list[j][0])
var ang = 1.5708-(angle + Math.atan(list[j][0]/list[j][1]))
list[j][0] = originX-(Math.cos(ang)*distanceToOrigin)*scaleX
list[j][1] = originY-(Math.sin(ang)*distanceToOrigin)*scaleY
}
addPolygonToMap(map, (list[0][0]), (list[0][1]), (list[1][0]), (list[1][1]), (list[2][0]), (list[2][1]), (list[3][0]), (list[3][1]), colour, floor)
}
});

PDFTron draw vertical box if layout is Horizontal

I have below code which will draw rectangle when user press "Shift + Left Mouse Click"
// Draw text box with alt + mouse left click
docViewer.on('click', (evt: any) => {
if (evt.shiftKey) {
// Get get window coordinates
const windowCoords = getMouseLocation(evt);
// Get current page number
const displayMode = docViewer.getDisplayModeManager().getDisplayMode();
const page = displayMode.getSelectedPages(windowCoords, windowCoords);
const clickedPage = (page.first !== null) ? page.first : docViewer.getCurrentPage();
// Get page coordinates
const pageCoordinates = displayMode.windowToPage(windowCoords, clickedPage);
// create rectangle
const rectangleAnnot = new instanceAnnotations.RectangleAnnotation();
rectangleAnnot.PageNumber = clickedPage + 1;
rectangleAnnot.X = pageCoordinates.x;
rectangleAnnot.Y = pageCoordinates.y - 14;
rectangleAnnot.Width = 200;
rectangleAnnot.Height = 14;
rectangleAnnot.StrokeColor = new instanceAnnotations.Color(255, 0, 0, 1);
rectangleAnnot.StrokeThickness = 2;
rectangleAnnot.Author = annotManager.getCurrentUser();
annotManager.addAnnotation(rectangleAnnot, false);
annotManager.redrawAnnotation(rectangleAnnot);
}
});
Now the issue is above code draw rectangle fine if PDF is vertical but if PDF is Horizontal then it draw Rectangle vertically. Please check below screenshot for reference.
As you can see on Page 1 it draws vertical box but on 2nd page its draws fine.
So how one can resolve it?
You need to account for page rotation to ensure your rect is aligned with the page.
Here is a quick example of how you can achieve that using the getCompleteRotation API, by setting width and height depending on the document rotation.
docViewer.on("click", (evt) => {
if (evt.shiftKey) {
// Get get window coordinates
const windowCoords = getMouseLocation(evt);
// Get current page number
const displayMode = docViewer.getDisplayModeManager().getDisplayMode();
const page = displayMode.getSelectedPages(windowCoords, windowCoords);
const clickedPage =
page.first !== null ? page.first : docViewer.getCurrentPage();
// Get page coordinates
const pageCoordinates = displayMode.windowToPage(
windowCoords,
clickedPage
);
// create rectangle
const rectangleAnnot = new Annotations.RectangleAnnotation();
rectangleAnnot.PageNumber = clickedPage + 1;
// Depending on doc orientation set Width and Height
const rotation = docViewer.getCompleteRotation(clickedPage);
const widthAndHeight = getWidthAndHeightBasedOnRotation(rotation);
// You will have to adjust the X, Y as well depending on rotation
rectangleAnnot.X = pageCoordinates.x;
rectangleAnnot.Y = pageCoordinates.y;
rectangleAnnot.Width = widthAndHeight.width;
rectangleAnnot.Height = widthAndHeight.height;
rectangleAnnot.StrokeColor = new Annotations.Color(255, 0, 0, 1);
rectangleAnnot.StrokeThickness = 2;
rectangleAnnot.Author = annotManager.getCurrentUser();
annotManager.addAnnotation(rectangleAnnot, false);
annotManager.redrawAnnotation(rectangleAnnot);
}});
const getWidthAndHeightBasedOnRotation = (rotation) => {
switch (rotation) {
case CoreControls.PageRotation["E_0"]:
return {
width: 200,
height: 14,
};
case CoreControls.PageRotation["E_90"]:
return {
width: 14,
height: 200,
};
case CoreControls.PageRotation["E_180"]:
return {
width: 200,
height: 14,
};
case CoreControls.PageRotation["E_270"]:
return {
width: 14,
height: 200,
};
}
};
You can access the CoreControls object from the instance. Please note that you will also need to tweak your X,Y coordinates based on the rotation. This is a good resource on PDF coordinates and viewer coordinates to help you wrap your head around that part.

Three.js Shader to modify TextGeometry

I'm completely new to three, hence this question which might be obvious to others.
So I achieved to load my font and build a TextGeometry accordingly. Additionally I created a kind of border using EdgesGeometry. This works fine.
But how do I achieve the geometries/mesh' to behave like this: https://edoardosmerilli.com/overview/ - In words: it kind of bends from left to center and vice versa (just like an old tube tv's screen) according to the scroll position. How do I achieve and effect like this? Is it a vertex shader? Is it three vectors that create this effect?
I'm thankful for every hint!
export default class Title {
constructor($el, $scene) {
this.scene = $scene;
this.title = $el.firstElementChild;
this.offset = new THREE.Vector2(0, 0);
const loader = new THREE.FontLoader();
loader.load('/RL-Unno.json', (font) => {
const geometry = new THREE.TextGeometry(this.title.innerHTML, {
font: font,
size: 120,
height: 1
});
geometry.center();
this.init(geometry);
})
}
init = (geometry) => {
const material = new THREE.MeshBasicMaterial({opacity: 0});
this.mesh = new THREE.Mesh(geometry, material);
this.getPosition();
this.mesh.position.set(this.offset.x, this.offset.y, 0);
this.scene.add(this.mesh);
const geo = new THREE.EdgesGeometry(geometry);
const outline = new THREE.LineBasicMaterial({
linewidth: 4
});
this.border = new THREE.LineSegments(geo, outline);
this.border.position.set(this.mesh.position.x, this.mesh.position.y, 0);
this.scene.add(this.border);
this.createListeners();
};
getPosition = () => {
const {width, height, top, left} = this.title.getBoundingClientRect();
this.offset.set(left - window.innerWidth / 2 + width / 2, -top + window.innerHeight / 2 - height / 2);
};
createListeners = () => {
this.title.addEventListener('mouseenter', () => {
gsap.timeline().set(this.mesh.material, {
opacity: 1
})
});
this.title.addEventListener('mouseleave', () => {
gsap.timeline().set(this.mesh.material, {
opacity: 0
})
});
};
update = () => {
if (!this.mesh) return;
this.getPosition();
gsap.timeline().set([this.mesh.position, this.border.position], {
x: this.offset.x,
y: this.offset.y,
});
}
}

An algorithm for animating a point over a closed path like square or triangle in canvas?

How to animate a point over a closed path. For the example below, I could pixel push this but I'm wondering if there is a better math(y) solution for animating over a path.
CodeSandbox
Note: I'm using a ctx.drawImg() to represent the point because I'd like the point to rotate along the path (image below code).
import "./styles.scss";
import o from "./letters/0.svg";
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const arena = 500;
const margin = 60;
const edge = arena - margin;
let data = [o];
var imgEls = [];
function drawArena() {
ctx.beginPath();
ctx.lineWidth = "3";
ctx.strokeStyle = "DeepSkyBlue";
const origin = [margin, margin];
ctx.moveTo(...origin);
ctx.lineTo(edge, margin);
ctx.lineTo(edge, edge);
ctx.lineTo(margin, edge);
ctx.lineTo(...origin);
ctx.stroke();
}
function loadImages() {
return data.map((item, i) => {
return new Promise((res, rej) => {
let img = new Image();
let svg = new Blob([item], { type: "image/svg+xml" });
let url = window.URL.createObjectURL(svg);
img.onload = () => {
imgEls.push(img);
window.URL.revokeObjectURL(url);
console.log("loaded");
res(img);
};
img.src = url;
});
});
}
Promise.all(loadImages()).then(() => {
// window.requestAnimationFrame(draw);
draw();
});
function draw(t) {
// window.requestAnimationFrame(draw);
drawArena();
imgEls.forEach((img, index) => {
const offset = index * img.width;
const x = margin + offset;
const y = margin - img.height;
ctx.drawImage(img, x, y);
});
}
If you're just tracking between 2 points; You're looking for Linear Interpolation.
Here's what it is:
In mathematics, linear interpolation is a method of curve fitting using linear polynomials to construct new data points within the range of a discrete set of known data points.
a demo in P5js
and a simple implementation in JS
function lerp(v0, v1, t) {
return v0*(1-t)+v1*t
}
via https://github.com/mattdesl/lerp/blob/master/index.js
Tracking over a complex path is decidedly more complex. Let me know if you need that functionality and I'll see what I can dig up.

Intersecting an isometric cube in Obelisk.js when mouse pointer intersects

I am using obelisk.js, which does not have a native way ( to my knowledge) of intersecting or raycasting for mouse picking, so I am trying to make my own methods, but I am not sure how to proceed.
Here's the code for a basic pen with a mouseover ( I want to detect when the mouse is on top of the cube):
Codepen sample
// Canvas & Scene Init:
var canvas = document.getElementById("canvas01");
var point = new obelisk.Point(210, 180);
var pixelView = new obelisk.PixelView(canvas, point);
// CUBE
var dimensionCube = new obelisk.CubeDimension(40, 40, 40);
var cubeColor = new obelisk.CubeColor();
var cube = new obelisk.Cube(dimensionCube, cubeColor);
var cubePos = new obelisk.Point3D(80, 80, 0);
pixelView.renderObject(cube, cubePos);
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
// Listener
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y ;
console.log(message);
}, false);
Thanks.
So after a bit of scratching my head I managed to add easel.js which has a handy hit area function and mouse event handling , the catch is that one has to crate a bitmap from the obelisk.js canvas and use that for the hit area without re-rendering.
I still need to figure out an efficient way of adding more than one primitive, here's the code so far:
And of course if you have a better,different or more native way that would be great as well:
// Canvas & Scene Init:
var canvas = document.getElementById("canvas01");
var ctx = canvas.getContext("2d");
var point = new obelisk.Point(210, 180);
var pixelView = new obelisk.PixelView(canvas, point);
var dimensionCube = new obelisk.CubeDimension(40, 40, 40);
var cubeColor = new obelisk.CubeColor();
var cube = new obelisk.Cube(dimensionCube, cubeColor);
var cubePos = new obelisk.Point3D(80, 80, 0);
pixelView.renderObject(cube, cubePos);
// Easel.JS glob:
var stage = new createjs.Stage("canvas01");
init();
function init() {
stage.enableMouseOver(10);
// we get the rendered canvas
var dataUrl = canvas.toDataURL();
// make a bitmap
var bitmap = new createjs.Bitmap(dataUrl);
// You could also add a hit area here
stage.addChild(bitmap);
// and the event handling we are after:
bitmap.on("mouseover", handleInteraction);
bitmap.on("mouseout", handleInteraction);
}
function handleInteraction(event) {
if (event.type === "mouseover") {
dimensionCube = new obelisk.CubeDimension(40, 40, 120);
cube = new obelisk.Cube(dimensionCube, cubeColor);
pixelView.clear();
pixelView.renderObject(cube, cubePos);
console.log("over");
} else {
dimensionCube = new obelisk.CubeDimension(40, 40, 40);
cube = new obelisk.Cube(dimensionCube, cubeColor);
pixelView.clear();
pixelView.renderObject(cube, cubePos);
console.log("out");
}
}
Pen: Obelisk.js + Easel.js basic Mouseover

Categories

Resources