How to integrate threejs modules with Aframe? - three.js

So I find a lot of interesting scripts that are built just with threejs, but I would like to somehow combine them with the ease of use that Aframe provides.
The below code starts by importing three.module.js - which I believe is already bundled with Aframe, so how can I include/import the required files and use them within a component?
I have had some joy including the three.module.js in my files and loading it exactly as below, but this seems like an unnecessary requirement/duplication of code.
<script type="module">
import * as THREE from '../build/three.module.js';
import { GUI } from './jsm/libs/dat.gui.module.js';
import { EffectComposer } from './jsm/postprocessing/EffectComposer.js';
import { RenderPass } from './jsm/postprocessing/RenderPass.js';
import { AfterimagePass } from './jsm/postprocessing/AfterimagePass.js';
EDIT:
Think I may be slowly getting there
<script src="./scripts/Pass.js"></script>
<script src="./scripts/CopyShader.js"></script>
<script src="./scripts/ShaderPass.js"></script>
<script src="./scripts/EffectComposer.js"></script>
<script src="./scripts/RenderPass.js"></script>
<script src="./scripts/AfterImageShader.js"></script>
<script src="./scripts/AfterImagePass.js"></script>
<script>
let composer;
let mesh;
let afterimagePass;
document.querySelector('a-scene').addEventListener('loaded', function () {
console.log(sceneEl.renderer.getSize());
composer = new THREE.EffectComposer( sceneEl.renderer );
composer.addPass( new THREE.RenderPass( sceneEl, sceneEl.camera ) );
afterimagePass = new THREE.AfterimagePass();
composer.addPass( afterimagePass );
composer.render(sceneEl, sceneEl.camera);
});
</script>
But now it's throwing this error
three.js:19204 Uncaught TypeError: t.onBeforeRender is not a function
at qe.render (three.js:19204)
at RenderPass.render (RenderPass.js:52)
at EffectComposer.render (EffectComposer.js:123)
at HTMLElement.<anonymous> ((index):982)
at HTMLElement.<anonymous> (a-node.js:263)
at a-node.js:128

Three.js doesn't currently support post processing for VR (https://github.com/mrdoob/three.js/pull/15840). While you might be able to get post processing to work in A-Frame using the default 2D camera, it currently breaks as soon as you switch to VR or AR -- this is due to the Three.js dependency, not A-Frame itself. To get 2D post processing to work in A-Frame you might try binding the EffectComposer to the A-Frame render loop (https://gist.github.com/donmccurdy/31560945d5723737e6c656a2974ab628).

Related

A-Frame: Adding animationClip from another glb to one that has no animation

I have a gltf model without an animation that I've loaded in aframe, and I'd like to add an animation that is connected to a different model. I've written some javascript to pull in the animation data and even bind it to the original GLB using GLTF loader, but not sure how to replace the aframe entity beyond just replacing the url.
Any help on how to solve this, or if there's a more efficient way to do this would be much appreciated! 🙂
HTML code:
<a-entity gltf-model="https://cdn.theoasis.xyz/public/bollywoodified/01.glb" id="center" position="0 0.03 -1.6" rotation="0 0 0" scale="1.3 1.3 1.3" animation-mixer\>\</a-entity\>
Javascript code:
import { GLTFLoader } from 'https://cdn.skypack.dev/three#0.129.0/examples/jsm/loaders/GLTFLoader.js';
getAnimations('https://cdn.theoasis.xyz/glb/djland.glb');
function getAnimations(glb) {
const loader = new GLTFLoader();
loader.load(glb, function ( gltf ) {
loader.load(oasis_data.metadata[0].glb, function (data) {
data.animations = gltf.animations;
});
});
}
I tried to pull the animationClip from another glb and was successful, and then was able to replace the animation array on the intended glb with the one from the animated glb. But I do not know how to actually update the entity within AFrame, nor do i know if this is the most efficient solution!

loading external geojson file into leaflet map by using leaflet ajax

I am trying to load external geojson by using leaflet ajax.
I think the structure of geojson is true. This is the link of it.
Here is what i did based on HERE:
in the head:
<script src="../external/js/leaflet.js"></script>
<script src="../external/js/leaflet.functionaltilelayer.js"></script>
<script src="../external/js/leaflet.ajax.min.js"></script>
In javascript:
var mymap = L.map('mapid',{ center: new L.LatLng(the_center_splitted[0],the_center_splitted[1]),maxZoom: 17, minZoom:11, zoom: 14}); //creating the map
var gs = new L.TileLayer('../external/maps/qom/gs/gs_{x}_{y}_{z}.jpg', {opacity: 1,scheme: 'TMS'}).addTo(mymap); //loading image layer
var geojsonLayer = new L.GeoJSON.AJAX("../external/map/qom/geojson/qom.geojson");
geojsonLayer.addTo(mymap);
But the geojson file is not shown and i get this error:
ncaught TypeError: L.GeoJSON.AJAX is not a constructor
I appreciate if any one can help.
Thank you.
What is "functionaltilelayer.js" for? In the code Snippet you don't need that.
And var gs = new L.tileLayer with a lower t - change that and try it again!
<script src="../external/js/leaflet.js"></script>
<script src="../external/js/leaflet.ajax.min.js"></script>
var mymap = L.map('mapid',{ center: new L.LatLng(the_center_splitted[0],the_center_splitted[1]),maxZoom: 17, minZoom:11, zoom: 14}); //creating the map
var gs = new L.TileLayer('../external/maps/qom/gs/gs_{x}_{y}_{z}.jpg', {opacity: 1,tms: true}).addTo(mymap); //loading image layer
var geojsonLayer = new L.GeoJSON.AJAX("../external/map/qom/geojson/qom.geojson");
geojsonLayer.addTo(mymap);
Your code seems okay - did you import
<script src='leaflet-ajax.js'></script>
If yes, please show your whole code!
Its a bit tricky to import files via AJAX.
First remember that the relative path your giving the AJAX() method should be a Your Geojson file should be path from the location of the leaflet-ajax script file. (Since it is there the AJAX-call gets done).
I would recommend a different approach (without AJAX calls):
Your GeJson file (rename it to gejson.js) should look like this:
var json = { "type": "FeatureCollection",
"features": [{
...
Import this file before your leaflet ajax code:
<script src="../../geojson.js" type="text/javascript"></script>
This will give you access to a variable called json which you then can use to import the json object in your layer:
var geojsonLayer = L.geoJSON().addTo(mymap);
geojsonLayer.addData(json);

Three.js import object from blender causes weird peeling of materials

I seem to have a problem importing a json object exported from Blender.
Everything seems to be working fine, but the materials aren't rendering correctly.
Does anyone have any idea as to why this peeling occurs?
I'm adding it simply via the ObjectLoader
function jsonLoad(url) {
var loader = new THREE.ObjectLoader();
loader.load(url, function (geometry, materials) {
scene.add(geometry);
});
}
Thank you very much in advance!

three.js with customization

Is it possible to add a model(say ,a mobile phone) using three.js in html5 canvas and then make it customizable like adding text,image etc.( on mobile ) using any canvas library,so as to make an interactive 3d model.
Thanks.
You could use a library called Dat.GUI, which allows you to create a quick user interface that can accept plain text input fields, drop downs, select boxes, as well as numerical sliders. Here's an example of it being used with a text input field, which you could use to input a texture/image URL.
It's a really powerful library that can be further styled with CSS, if needed. This is all the code you need to get up and running (as you can see below, the object's properties get modified directly by Dat.GUI via invoking gui.add(object, 'property')):
<script type="text/javascript" src="dat.gui.js"></script>
<script type="text/javascript">
var FizzyText = function() {
this.message = 'dat.gui';
this.speed = 0.8;
this.displayOutline = false;
this.explode = function() { ... };
// Define render logic ...
};
window.onload = function() {
var text = new FizzyText();
var gui = new dat.GUI();
gui.add(text, 'message');
gui.add(text, 'speed', -5, 5);
gui.add(text, 'displayOutline');
gui.add(text, 'explode');
};
</script>
Yes. Three.js uses a canvas to render the 3D things and you can use any HTML tools to make the rest of that web page how you want.

ColladaLoader: Could not find the skeleton for the skin

I was trying to render a primitive character I made in 3dsmax, but seems like there's something wrong with my exported DAE file or just ColladaLoader is unable to process it correctly.
Scene consists of an animated biped skeleton, simple rigged character using Physique modifier, one static box and an animated one.
Here's my code:
<script src="three.js" type="text/javascript"></script>
<script src="ColladaLoader.js" type="text/javascript"></script>
<script type="text/javascript">
var size_width = window.innerWidth;
var size_height = window.innerHeight;
var player;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, size_width/size_height, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(size_width, size_height);
document.body.appendChild(renderer.domElement);
camera.position.x = 100;
camera.position.y = -50;
camera.position.z = 7;
camera.rotation.x = 1.4;
var player_loader = new THREE.ColladaLoader();
player_loader.load( "running_babe.dae", function(collada) {
player = collada.scene;
init();
});
function init() {
scene.add(player);
render();
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
</script>
But all I get are those two boxes and a error:
ColladaLoader: Could not find the skeleton for the skin.
Here's exported DAE file I use - http://touhou.ru/upload/ff72eb0b40adf5c97286a1bcb164e1f0.DAE
Any suggestions?
Update: After rigging character with skin modifier I came up with the same result - could not find the skeleton for the skin.
Here's the link to exported dae with skin modifier - http://touhou.ru/upload/af6ba52b7bff5fa2b0f6ba3f704a3b77.dae
I had the same problem and spent days playing with exporter settings before i started reading the threejs colladaloader source and figured it out. so in case you haven't solved it yet, here's what you have to do:
First: when you export your model from max, make sure none of the elements in your scene have the same name as your filename (or your geometry wont show up this has something to do with generated ids in the DAE file)
Now, 3DSMax somehow neglects to export a node, so you have to add that manually:
open the running_babe.dae file in a text editor
look for an <instance_controller url="...."/> node and rewrite it to:
<instance_controller url="....">
<skeleton>#xxxxx</skeleton>
</instance_controller>
wherein 'xxxxx' is the id(=element/bone name in 3dsmax) that is the root element of your skeleton hierarchy. and don't forget the 'hash' at the beginning! :)
hope that solves it for you. i haven't tried animation yet, but i will now, and let you know if there's anything missing from this solution.
edit: nevermind, apparently i just scratched the surface of the tip
of a huge frigging iceberg.. seems like getting collada(from 3dsmax
2013) + skinned animation working is a pain.. i'll look at writing a new json exporter.
the format seems straight forward and well documented, plus, there's the old .ms file
from github to start from. good luck to you! if you find something, be so kind as to post
your method here, would you? :)
The default plugin that comes with 3ds max does not work. You need to use the OpenCollada plugin. Then you can follow the collada loader example. You get bones, animations and all!

Resources