When I've got a sphere which is defined largely using a mixin, e.g.
<a-mixin id="beach-ball" geometry="primitive: sphere; radius: 1"></a-mixin>
And used like so:
<a-entity mixin="beach-ball" id="beach-ball-main"></a-entity>
Is there a way I can then find out the radius of the beach ball using JS while the scene is running? Attempts at doing this don't work:
var ballRadius = document.getElementById('beach-ball-main').getAttribute('geometry').radius;
... that just returns a blank geometry attribute, which makes sense as the entity itself doesn't have the geometry defined.
However, surely there's a way to request the current radius of the ball in the above example, even though it's defined in a mixin?
All help appreciated!
getAttribute() works as long as you have an up to date version of A-Frame!
Related
I've been building something in aframe (using the current master build from github as of 23rd March 2018) and have noticed that there are two sets of rotations that are identical that I don't think should be.
A model looks the same with its rotation attribute "270 90 90" and "270 180 0".
Similarly - setting the rotation attribute to "270 270 90" and "270 0 0" look the same.
I created a little demo to show this here - http://marcamillian.com/VR/rotationIssue.html.
Is this a bug or am I mis-understanding something?
=== Further information ===
I came across this when trying to add rotating animations a model from "270 90 0" along its roll axis and yaw axis and not getting the same motion on each.
After checking all of my functions I started setting the attribute on the model directly and getting the model looking the same for different rotation positions.
This is a pretty common problem in 3D computer graphics. Welcome to the gimbal lock problem! It is basically an issue you run into when trying to set rotations using "Euler" angles, especially when rotating in multiples of 90 degrees. If you are going to rotate like this try to only rotate by two axes (e.g. x and y) instead of all 3 (x,y,z).
More information here on gimbal lock: https://www.youtube.com/watch?v=zc8b2Jo7mno&feature=youtu.be
An even better practise is to rotate using quaternions instead. I will also note that it is best practise to use components to make sure A-Frame is available to modify, or not as recommended a "loaded" event listener on a-scene (see this SO question for more info. How to detect when a scene is loaded in A-Frame?):
//listen for scene load s0 we know Aframe and Threejs are around to access. A snipped of your code, modified slightly for some direction ...
document.querySelector('a-scene').addEventListener('loaded', function () {
//AFRAME loaded
const scene = document.querySelector('a-scene');
const arrowElem = scene.querySelector(".shape-container");
//now set your click listener
setButton.addEventListener('click',function(){
let rotationValue = `${inputPitch.valueAsNumber} ${inputYaw.valueAsNumber} ${inputRoll.valueAsNumber}`
//arrowElem.setAttribute('rotation', rotationValue); //your way
//this doesn't work well ...
//arrowElem.object3D.rotation.set( THREE.Math.degToRad(inputPitch.valueAsNumber),
THREE.Math.degToRad(inputYaw.valueAsNumber),
THREE.Math.degToRad(inputRoll.valueAsNumber)
);
//consider how you can use quaternions instead
let quaternion = new THREE.Quaternion();
quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 ); //might have to change your logic to better use this functionality ...
})
});
I have been trying to create a simple application whereby a 360 image is shown on a Sphere. The next step is to dynamically add 'hotspots' onto this image as the user pans around.
I've tried many different approaches (including delving deep deep into Three.JS) but it doesn't seem to be that easy. (UVs, positions, vertices etc).
A-Frame is awesome at making it super simple for developers to get up and running. I managed to find an example whereby there were two 'hotspots' on a sphere, which when hovered/focused, the sphere background changed.
I'm looking to create a new 'hotspot' in the cameras direction, however this is proving to be quite difficult because the camera position never changes but the rotation does.
For example, after panning, I see the following:
<a-camera position="0 2 4" camera="" look-controls="" wasd-controls="" rotation="29.793805346802827 -15.699043586584567 0">
<a-cursor color="#4CC3D9" fuse="true" timeout="10" material="color:#4CC3D9;shader:flat;opacity:0.8" cursor="maxDistance:1000;fuse:true;timeout:10" geometry="primitive:ring;radiusOuter:0.016;radiusInner:0.01;segmentsTheta:64" position="0 0 -1" raycaster=""></a-cursor>
</a-camera>
Ideally, to create a new hotspot in this position, I assumed all I'd need to do it add the rotation values to the position value and that'd be the correct place for the hotspot, but unfortunately, this doesn't work, either the hotspot is in the wrong position, it's not facing the camera or its no longer in view.
How can I create a 'hotspot' in the cameras viewpoint (in the middle)?
I've setup a codepen which should help show the problem I'm having better. Ideally when I pan around and click 'create hotspot', a 'hotspot' should be created directly in the middle (just like the red and yellow ones).
Thanks!
UPDATE: An idea I've had is to have a secondary sphere (smaller radius) with no background. If it's easy to know the XYZ coordinates of the camera view intersecting it, then this is made super simple. Is there a way of finding this out?
Without any intersection, when you know the position of the camera, this is the vector which needs to be: negated, normalized, multiplied by a scalar value which equals to the radius of the sphere. The result is the point of your new hotspot.
var pos = camera.position.clone().negate().normalize().multiplyScalar(sphereRadius);
jsfiddle example
Yes, I think your second idea is right, you can make a new sphere which has seam position with your camera. If you want to make a new 'hotspot' on your center of screen. you can make a raycaster from camera to the 'hotspot' and it will intersect the sphere. But, you should set the material's side property with 'doubleside', if not, you won't intersect the sphere. then, you can get the intersect[0].point.
var pos = new THREE.Vector3().copy(cameraEl.getComputedAttribute("position"));
cameraEl.object3D.localToWorld(pos);
var vector = new THREE.Vector3(( event.clientX / window.inneenter code hererWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
vector = vector.unproject(camera);
var raycaster = new THREE.Raycaster(pos, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects([sphere],true);
if(intersects.length > 0)
{
console.log(intersects[0].point);
}
`
I have a Rect assigned to a variable myrect:
var myrect = new Rect (250,0,20,200);
I thought that writing:
console.log(myrect.x);
would output 250 but, it says "undefined".
I would like to know how I can redraw this rectangle by performing
arithmetic on its x and y coordinates.
The way to access the x and y properties is through the attr() method.
console.log(myrect.attr('x'));
See it in the documentation. But I have to admit, the documentation isn't that beginner-friendly yet.
I'm trying to apply a texture to a geometry created at runtime, reading a binary asset from a remote server.
I create the geometry assigning UVs (geometry.faceVertexUvs = uvs;), normals (face.vertexNormals.push(...)) and tangents (face.vertexTangents.push(...)).
If I try to create a mesh with a basic material, there are no problems, but when I create the mesh with that geometry and I try to apply my texture, webgl doesn't display any geometry and I get this warning:
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1
Does anybody know what is going on? I think that my geometry has something wrong, because if I use a THREE.Sphere, I can actually apply the texture.
But everyone told me that in order to apply texture I need UVs, and I have'em.
I think that my faceVertexUvs is wrong.
The real question is: geometry.faceVertexUvs.length should be equal to geometry.vertices.length, or it should be equal to geometry.faces.length ?
Thank you very much.
PS: I've already read the following posts
WebGL drawElements out of range?
Three JS Map Material causes WebGL Warning
THREEjs can't use the material on the JSON Model when initializing. Gives me WebGL errors
Loading a texture for a custom geometry causes “GL_INVALID_OPERATION” error
problem solved!!
#GuyGood: you're right when you say that every vertex need a UV-Vector2, but it's wrong to say that geometry.faceVertexUvs.length should be equal to geometry.vertices.length...
it seems that facevertexUvs is a matrix, and not an array..well, it is an array of arrays..not properly a matrix..in fact I think it can be used to handle multi-mesh objects..if facevertexUvs.length == 3, we have 3 submeshes, so 3 arrays..each one of them has a length equal to the number of faces of a particular submesh..and every face knows the UV mapping about the 3 vertices defining that face..
hope this is clear and helpful!!
I would like to draw sector of circle on map defined by point, radius, startAngle and stopAngle. I found lots of exmaples but with polygons etc whitch was too complicated for my case.
Thanks for any help!
a Circle is an object with no defined sides. Only a radius and a center point.
You are required to use a polygon to build a semi circle as it is a two sied object
There is not always an easy way out in coding, and typicaly they are the bad ways to do things (unless your talking about somthing like JQ/Bootstrap)
Here is a fairly stright forware implementation
http://googlemaps.googlermania.com/google_maps_api_v3/en/draw-semi-circle.html
This was refered in this question
Google Maps Polygon Incorrectly Rendered
they even provide a working example for you to rip apart
http://maps.forum.nu/temp/gm_bearing.html