aframe | : a : Web framework for building virtual reality experiences | Augmented Reality library
kandi X-RAY | aframe Summary
Support
Quality
Security
License
Reuse
- Initialize a new WebGL renderer .
- Constructs a WebGL textures
- Creates a new ColorState .
- Create a fog object .
- Create a binding state object .
- Creates the WebGL program objects
- Creates state object from parsed file
- Creates a new WebVRVR instance .
- Parse a JSON model in FBXTree . Objects . Geometry .
- Shows the shadow map .
aframe Key Features
aframe Examples and Code Snippets
// Register all the ng-generated tags in your application so that a-frame
// recognizes them as one of it its own, and thus properly inserts them into the
// scene. If ng tags are not registered with a-frame then ng will only insert
// them into to the DOM but *not* into the a-frame scene.
// A-frame's 'registerPrimitive' *must* be called in angular's polyfill.js after
// 'aframe.js' and before 'zone.js'.
//
AFRAME.registerPrimitive('app-sub-scene-a', { mappings: {} }); //<- specify all your ng tags starting here
AFRAME.registerPrimitive('app-sub-scene-b', { mappings: {} });
//import 'aframe'; <- alternate way to load aframe
import '../node_modules/aframe/dist/aframe-master'; //<- useful if you want to call a specific version of a-frame
import '../init_scripts/register-ng-primitives'; <- put your script here
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI. <- need to call before this
TypeError: "detachedCallBack" is read-only.
toggleSubScenes() {
console.log(`WrapperSceneComponent.toggleSubScenes: entered`);
let ssa = document.querySelector('app-sub-scene-a');
let ssb = document.querySelector('app-sub-scene-b');
let ssaVisible : any= ssa.getAttribute('visible');
let ssbVisible : any= ssb.getAttribute('visible');
ssa.setAttribute('visible', ssaVisible ? 'false' : 'true');
ssb.setAttribute('visible', ssbVisible ? 'false' : 'true');
}
$(document).ready(function() {
// Page is fully loaded, generate the iframe and set attributes
var aFrame = $('');
$(aFrame).attr('src', 'https://www.youtube.com/embed/EU7PRmCpx-0');
$(aFrame).attr('width', '560');
$(aFrame).attr('height', '315');
// iframe element is created, append it to the body (or another element)
$('body').append(aFrame);
});
</code></pre>
// get three.js object from aframe entity
var el = document.querySelector('#my-element');
var object = el.getObject3D('mesh');
// compute bounding box
var bbox = new THREE.Box3().setFromObject(obj);
console.log(bbox.min, bbox.max)
const AFRAME = window.AFRAME;
/*
* Scales the object proportionally to a set value given in meters.
*/
AFRAME.registerComponent('natural-size', {
schema: {
width: {
type: "number",
default: undefined // meters
},
height: {
type: "number",
default: undefined // meters
},
depth: {
type: "number",
default: undefined // meters
}
},
init() {
this.el.addEventListener('model-loaded', this.rescale.bind(this));
},
update() {
this.rescale();
},
rescale() {
const el = this.el;
const data = this.data;
const model = el.object3D;
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize();
if ( !size.x && !size.y && !size.z ) {
return;
}
let scale = 1;
if ( data.width ) {
scale = data.width / size.x;
} else if( data.height ) {
scale = data.height ( size.y);
} else if( data.depth ) {
scale = data.depth / size.y;
}
el.setAttribute('scale', `${scale} ${scale} ${scale}`);
},
remove() {
this.el.removeEventListener('model-loaded', this.rescale);
}
});
let body = el.body // el = aframe entity
body.velocity.set(0,0,0);
body.angularVelocity.set(0,0,0);
body.vlambda.set(0,0,0);
body.wlambda.set(0,0,0);
import AFRAME from 'aframe';
AFRAME.registerComponent('score-counter', {...});
import 'aframe-helper'
Trending Discussions on aframe
Trending Discussions on aframe
QUESTION
I am using a networked A-frame to generate a new entity when the page is loaded. I want to add a few functionalities on those entities like hover, on click, etc. I tried making it clickable but it didn't work.
function rigClick(){
console.log("Entity Clicked");
}
I also tried using the register component but I am unable to get the results.
AFRAME.registerComponent('click-handler', {
init: function () {
let entity = document.querySelector('#rig')
entity.addEventListener('click', (e) => {
console.log("You just clicked on entity");
})
}
});
ANSWER
Answered 2022-Mar-30 at 09:13If you want to use your mouse, you need a cursor
which will map 2D mouse clicks onto 3D rays checking whats under the mouse cursor:
Works the same in aframe-networked as long as you add the component to the networked-template
so that every new 'player' has the component attached:
QUESTION
I don't want the player to go through walls. I tried aframe extras but it doesn't work in current aframe version. Is there any other way or solution that works in Aframe 1.3.0?
ANSWER
Answered 2022-Mar-17 at 23:18You can use the simple-navmesh-constraint components from AdaRoseCanon ( it's working fine with a-frame 1.3.0):
Source code here: https://github.com/AdaRoseCannon/aframe-xr-boilerplate
Demo here: https://aframe-xr-starterkit.glitch.me/
QUESTION
I am using A-Frame and pdf.js to create an application to view PDF files in VR. The application works as expected on desktop, including advancing to the next page of the PDF document and re-rendering to a canvas.
When running in a browser in VR (tested with Quest 2), the first attempt renders as expected. However, when rendering a second document page to the canvas, the new image fails to appear unless exiting VR mode, at which point the new texture appears as expected.
I have tried setting the associated material map.needsUpdate
repeatedly (in an A-Frame component tick loop) to no effect. While experimenting, I also noticed that if you try to render a new PDF page a second time and then another page a third time (advancing by two pages while in VR mode), when exiting VR mode, only the texture from the second time appears; the data from the third render appears to be lost - I wonder if this is related to the primary issue.
Code for a minimal example is below, and a live version is available at http://stemkoski.net/test/quest-pdf-min.html . When viewing the example in desktop mode, you can advance to the next page by opening the browser JavaScript console and entering testBook.nextPage();
and see that the image changes as expected. You can test in VR mode with a Quest headset; pressing the A button should advance to the next page.
The question is: how can I render pages of a PDF document to the same canvas, multiple times, while in VR mode in A-Frame?
A-Frame + PDF.js
ANSWER
Answered 2022-Mar-05 at 14:51Found an answer here:
requestAnimationFrame doesn't fire when WebXR is engaged
Its quite relevant because pdf.js
uses requestAnimationFrame
by default when rendering the image onto the canvas.
It can be toggled though - the pages render function has an option intent
, which is later on used to determine whether to use requestAnimationFrame.
The sources You use are slightly different (older?), but if you search for creating the InternalRenderTask
in the render
function of the ProxyPDFPage
- it's all there:
const internalRenderTask = new InternalRenderTask({
callback: complete,
params: {
canvasContext,
viewport,
transform,
imageLayer,
background
},
objs: this.objs,
commonObjs: this.commonObjs,
operatorList: intentState.operatorList,
pageIndex: this._pageIndex,
canvasFactory: canvasFactoryInstance,
webGLContext,
useRequestAnimationFrame: renderingIntent !== "print",
pdfBug: this._pdfBug
});
You can set the intent
to print in your renderContext
object:
// 'interactive-pdf'.render()
const renderContext = {
canvasContext: context,
viewport: pageViewport,
intent: "print"
};
const renderTask = page.render(renderContext);
And it seems to be working properly:
I'm not sure, if setting the intent to print
won't cause undesired effects (it affects other settings as well), so disabling useRequestAnimationFrame
in the source does the trick as well.
Check out the version with the 'print' intent, or the one with the modified pdfjs source code.
QUESTION
I want my A-frame camera to be behind the model and work as a TPP. I want a model to sync with the camera and rotate and move where ever the camera is moving but it should not move if the camera is pointing up and down it should not look like the model is stuck on the camera.
If I move the camera the box should also move. Output image
ANSWER
Answered 2022-Mar-03 at 18:25The easiest way would be simple reparenting:
A more complex, but flexible solution, would be creating a controller with javascript. Lets say we want to:
- Make the camera follow the box
- Make the box rotate with the camera
- Preferably not instant, but smooth.
we could do it with a component like this:
The best way would be to re-use the orbit-controls, but afaik they won't work with wasd controls without some customization
QUESTION
I have some code that restricts the camera movement in A-frame so when the camera moves 10 spaces away from the starting point, they are teleported back to the position 0, 1.6, 0. Currently, this works is the players x or y axis moves 10 spaces away from their starting point. How can I modify this so the player is only teleported back if only their y position moves 10 spaces from their starting point? Code:
ANSWER
Answered 2021-Oct-04 at 09:51If you want to check only the y
axis, then it's as simple as checking the difference of two numbers:
// distance = |y_position - y_start|
const y = this.el.object3D.position.y;
const distance = Math.abs(0 - y);
if (distance > 10) {// do your stuff}
Something like this:
QUESTION
I've created a proof-of-concept SPA (source code / demo) which loads stereoscopic images from a web server and renders them in stereoscopic 3D using the aframe-stereo-component for A-frame.
Testing this on a Quest 2 in the Oculus Browser and Firefox Reality, this works fine: each image appears in 3D when viewed in immersive VR mode via WebXR.
However, after scrolling through a number of images (usually 8 to 12), the slideshow stops working. In Firefox Reality, this manifests by the app just freezing and becoming unresponsive.
In Oculus Browser, the image description is displayed but the image area remains black. Connecting the Quest 2 to a PC with adb and inspecting the page using Chrome DevTools, I can see the following output when this occurs:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:07:59.195 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:07:59.195 [.WebGL-0x55930300]RENDER WARNING: texture bound to texture unit 0 is not renderable. It might be non-power-of-2 or have incompatible texture filtering (maybe)?
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_OUT_OF_MEMORY : glTexImage2D:
23:08:03.340 [.WebGL-0x55930300]GL ERROR :GL_INVALID_OPERATION : glGenerateMipmap: Can not generate mips
23:08:03.499 WebGL: too many errors, no more errors will be reported to the console for this context.
Admittedly the images being loaded are large JPS files (2 to 3Mb) and each image is rendered twice: once for each eye. However, an element is used to load the image content by adding it to the DOM and when the next image is requested, this is removed and nulled to invalidate the image content so in theory only one image should be loaded at any one time. Therefore I'm assuming there must be a memory leak somewhere which is causing the memory to get filled up after a number of images have been loaded but I'm not sure where it's leaking. I'm not able to reproduce the issue on a PC using Chrome/Firefox but this is probably because it has more memory than the Quest 2.
Relevant source code extracts:
const stereoImageId = 'fullsize-image'
const _stereoImage = '#'+stereoImageId;
const leye = $('#left-image')[0];
const reye = $('#right-image')[0];
const $assets = $('#assets');
const removeStereoImage = function(){
let $stereoImage = $(_stereoImage);
if($stereoImage.length){
let stereoImage = $stereoImage[0];
stereoImage.onload = stereoImage.onerror = null;
$stereoImage.attr('src', '').remove();
$stereoImage = stereoImage = null;
}
};
const unloadStereoImage = function(){
removeStereoImage();
leye.setAttribute("material", "src", '');
reye.setAttribute("material", "src", '');
setStereoImageVisibility(false);
};
const setStereoImageVisibility = function(visible){
leye.setAttribute("visible", visible)
reye.setAttribute("visible", visible)
};
const showImg = function(url, description){
function onImgLoaded(){
leye.setAttribute("material", "src", _stereoImage);
reye.setAttribute("material", "src", _stereoImage);
setStereoImageVisibility(true);
}
unloadStereoImage();
let stereoImage = document.createElement('img');
stereoImage.setAttribute('id', stereoImageId);
stereoImage.setAttribute('crossorigin', "anonymous");
stereoImage.setAttribute('src', url);
stereoImage.onload = onImgLoaded;
$(stereoImage).appendTo($assets);
};
I've also raised this as an issue in the source code repo
ANSWER
Answered 2021-Oct-04 at 09:18The asset management system (a-assets
) is intended to help with preloading assets, not throwing them in and out at runtime.
Removing the element from the assets won't dispose the texture (which is cached within the material system).
You can access and clear the cache, but I'd try managing the images 'manually',
loading the image via
new THREE.Texture(src)
like the material system doesapply the material with
element.getObject3D("mesh").material.map = texture;
material.needsUpdate = true;
remove the old texture with texture.dispose()
Thought that the textures are too big, but I guess each one would crash.
QUESTION
I'm using Javascript and A-frame. I want to be able to get a random block from the list of blocks and I want it to move down by 1. I can't seem to get any of the blocks to appear randomly on the load current. Below is the code I created to make my tetris board but it's currently giving me slight issues.
I am getting the error
"message": "Uncaught SyntaxError: Unexpected end of input",
I'm not sure what that means?
var zigZag = document.querySelector("#zigZag");
var fork = document.querySelector("#fork");
var box = document.querySelector("#box");
var line = document.querySelector("#line");
var plane = document.querySelector("#plane");
//timer
// let hour = 0;
// let minute = 0;
// let second = 0;
// let millisecond = 0;
// let cron;
var newBlock, blocks, element, blocksOnPlane, planeBlock;
// Describe this function...
newBlock = [];
blocks = [zigZag, fork, line, box];
blocksOnPlane = [];
document.addEventListener("load", start);
function start() {
while (true) {
new Promise((res) => setTimeout(() => res(chooseBlock()), 10));
console.log(newBlock.length);
for (var element_index in newBlock) {
element = newBlock[element_index];
moveBlock(element);
plane.detectCollisionsWith(newBlock[element_index], function (
collidedObject
) {
newBlock = collidedObject;
newBlock.object3D.position.y = 0;
blocksOnPlane.unshift(planeBlock);
newBlock.shift();
});
// for (var element_index in blocksOnPlane) {
// element = blocksOnPlane[element_index];
// newBlock.detectCollisionsWith(planeBlock, function (collidedObject) {
// element.setY(element.getY() + 0)
// planeBlock = collidedObject;
// blocksOnPlane.unshift(planeBlock);
// newBlock.shift();
// })
// }
}
}
}
document.addEventListener("keydown", function (event) {
if (event.keyCode === 37) {
element.object3D.position.x += -1;
}
//top
else if (event.keyCode === 38) {
element.object3D.position.x += 1;
}
//right
else if (event.keyCode === 39) {
element.object3D.position.x += 1;
}
//bottom
else if (event.keyCode === 40) {
element.object3D.position.x += -1;
}
});
function moveBlock(element) {
document.createTimer("timer1", 1 * 1000, function () {
element.object3D.position.y += -1;
});
}
function listsGetRandomItem(list, remove) {
var x = Math.floor(Math.random() * list.length);
if (remove) {
return list.splice(x, 1)[0];
} else {
return list[x];
}
}
// Describe this function...
function chooseBlock() {
var tetrisBlock = document.clone(listsGetRandomItem(blocks, false));
tetrisBlock.visible = true;
tetrisBlock.object3D.position.x = 0;
tetrisBlock.object3D.position.y = 7.5;
tetrisBlock.object3D.position.z = -14;
newBlock.unshift(tetrisBlock);
}
start
pause
reset
ANSWER
Answered 2021-Dec-28 at 22:45Not sure where did you get document.clone(element)
as the document
object doesn't seem to have a cloning utility.
There is a element.cloneNode() method which works fine - we can use it within a custom component, which will also handle the entity lifecycle:
COPY
You can move it down with interval timeouts, or a tick / throttledTick handler. This could be done within a system, which would manage created entities (moving down, collisions).
A simple "moving down" version could look like this:
NEW
Sooner or later You'll probably run into performance issues (once there are several nodes) and it would be best to dive into mesh instancing (or at least check the performance guidelines)
QUESTION
I have a scene I've created using A-frame (https://aframe.io) where currently I have a green box glued to the camera at all times. When the camera turns, the box will move alongside the camera. What I'm wondering is how can I set the box to the top right corner of the screen no matter what the device is. Currently I'm using the position aframe property to position the box at the top right but on smaller devices the box won't show and on bigger devices it's in the middle of the screen. How can I make it so the box is glued to the top right no matter what the screen size is?
Current code:
Fiddle containing code: https://jsfiddle.net/AidanYoung/0sjLrhfg/
ANSWER
Answered 2021-Dec-22 at 01:25You could use the pythagorean theorem to place a green box at the top-left corner of the camera. However, I think given your use-case it would be easier to simply render a separate scene in the corner using the Renderer.setViewport()
method
See the code sample below. In essence you're creating 2 scenes, and 2 cameras. The main scene will contain your 3D world and probably a perspective camera to look at it. The small scene will contain perhaps a simple plane and an orthographic camera to render it flat without perspective. Then on each frame you:
- Clear the renderer's buffers
- Render main across the entire window
- Clear only depth buffer, preserving the color
- Render small scene in a 100x100 box on top of step 2
const renderer = new THREE.WebGLRenderer({/*...*/});
// This prevents the renderer from clearing buffers in between renders
renderer.autoClear = false;
// Main will hold 3D objects
const sceneMain = new THREE.Scene();
scenemain.add(some3DObject);
// Small scene for top-left corner
const sceneSmall = new THREE.Scene();
sceneSmall.add(videoObject);
renderLoop() {
// Clear renderer buffers
renderer.clear();
// Render main scene across full screen
this.renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
renderer.render(sceneMain, cameraMain);
// Reset depth buffer
renderer.clearDepth();
// Render small scene in a 100x100 square
this.renderer.setViewport(0, window.innerHeight - 100, 100, 100);
renderer.render(sceneSmall, cameraSmall);
}
You can see a live demo of this "Picture-in-picture" approach in action in this example.
QUESTION
I'm starting to learn aframe and want to use it with an Oculus Quest 2. I have the hands displayed and I'm trying to move around the VR world but when I move the hands don't move ... how to make the hands follow the camera? thanks
This is my code
ANSWER
Answered 2021-Dec-19 at 07:56I finally found ...
At the beginning I put the controllers in the camera ... but I had to put them in #rig
QUESTION
I am using A-Frame 1.2.0. I have a gltf model on scene and I want to add flat shader this model.
And my flat shader code is from here
const FlatShader = {
schema: {default: true} ,
init() {
this.el.addEventListener('object3dset', this.update.bind(this));
},//init
update() {
const mesh = this.el.getObject3D('mesh');
const { data } = this;
if (!mesh) {
return;
}
mesh.traverse(function(node) {
if (node.isMesh && data) {
const mat1 = new THREE.MeshBasicMaterial();
node.material = mat1;
node.material.needsUpdate = true;
}
});
},//update
}; // FlatShader
export default FlatShader
Flat shader is working but after added flat shader, model animations are not working. Model stays in its static pose.
Any ideas what could be causing the problem ? I may be missing something, but i have no clue how to solve this.
ANSWER
Answered 2021-Dec-13 at 12:05In a-frame
s version of threejs (modified 125) , You need to "tell" the material, that your model utilizes "skinning" for animations:
material.skinning = true;
Since three r.129 this is no longer necessary
So, all you need is to change the Materials skinning
property to true:
Cesium man model is from the Kronos Group glTF sample models repo
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install aframe
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page