How to animate react-three/drei shaderMaterial with react-spring - react-three-fiber

I am trying to use react-spring values to animate uniforms in my custom shader built using the react-three/drei shaderMaterial.
This is my basic setup:
const { speed } = useSpring({
speed: animate ? 1 : 0,
});
return (
<mesh>
<planeBufferGeometry args={[1,1]}/>
<animated.customMaterial uSpeed={speed} />
</mesh>
)
When I prepend animated, I get the following message:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Without adding animated I get no result in the shader at all.
Any help would be greatly appreciated.

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!

JeelizFaceFilter and THREEJS issue with gltf and texture models

Goal
I'm stuck since yesterday with an issue on modifying a JeelizFilterFace example. My goal is to create my own filters, so I started the the luffy's hat tutorial, which explains that : https://jeeliz.com/blog/creating-a-snapchat-like-filter-with-jeelizs-facefilter-api-part-1-creating-your-first-filter/
Quick description of the problem
My problem is simple : I can't have the glTF example working with glTF models. It always show me a black shape, without the texture.
Details of the problem
The tutorial explains that the model have to be generated with a Blender exporter addons, in order to create the json file which is the model. But the Blender exporter is not supported anymore.
This is why I try to use ThreeJS with the GLTF loader (which is the best solution according to all the tutorials).
My problem is that I can't see any texture on any of my models, when I load it with JeelizFaceFilter/Threejs. I only have the black shape.
Here is what I did :
First, I did all the tutorial to be sure I can run the FilterFace tool, except for the exporting model from Blender part. So, I just copied the exported resources from the Jeeliz repo. The FilterFace works well : the hat is visible, with the texture and I can play with the THREEJS params.
Because I couldn't export the JSON from blender, i wanted to try to use the GLTF 2.0 model, I tried this model, which is working in the gltf-viewer tool (see picture below) : https://s3.eu-west-3.amazonaws.com/com.julianlecalvez/LuffysHat.zip
So far everything seems ok, but when I try to use this glTF loader example in the glTF demos (https://github.com/jeeliz/jeelizFaceFilter/tree/master/demos/threejs/gltf_fullScreen), it displays my hat in black. I have the good shape, but no texture (or no light?). I just replaced the model URL in this file. And I'm not even sure that the default model (the helmet) is displaying any texture.
I tried with a model from SketchFab, and I have the same : Black shape, no texture.
I put here the code to init the view, when I was trying to redo it outside of the demo file :
let init_view = function(spec) {
const threeStuffs = THREE.JeelizHelper.init(spec, null);
const SETTINGS = {
gltfModelURL: 'objects/luffys_hat_gltf/luffys_hat.gltf',
offsetYZ: [1,0],
scale: 2.2
};
// const loader = new THREE.GLTFLoader();
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load( SETTINGS.gltfModelURL, function ( gltf ) {
gltf.scene.frustumCulled = false;
// center and scale the object:
const bbox = new THREE.Box3().expandByObject(gltf.scene);
// center the model:
const centerBBox = bbox.getCenter(new THREE.Vector3());
gltf.scene.position.add(centerBBox.multiplyScalar(-1));
gltf.scene.position.add(new THREE.Vector3(0,SETTINGS.offsetYZ[0], SETTINGS.offsetYZ[1]));
// scale the model according to its width:
const sizeX = bbox.getSize(new THREE.Vector3()).x;
gltf.scene.scale.multiplyScalar(SETTINGS.scale / sizeX);
// dispatch the model:
threeStuffs.faceObject.add(gltf.scene);
});
// CREATE THE CAMERA
THREECAMERA = THREE.JeelizHelper.create_camera();
}

Blend Filter Not apply when call canvas function `loadFromJson`

When I perform blend filter on the image and convert canvas into JSON
Then It again I load canvas from that JSON, at that time my filter not applied.
I am using a fabric version 1.7.22
My filter code is like below :
canvas.getActiveObject().filters.push(new fabric.Image.filters.BlendColor({
color: '#ff0000',
mode: 'add',
alpha: 0.8
}))
canvas.getActiveObject().applyFilters(canvas.renderAll.bind(canvas));
All other filter is working perfectly after the canvas load into JSON but only blend filter not work.
Is there any property missing in my filter?
I have created one fiddle that represents the issue :
http://jsfiddle.net/Mark_1998/1pc95xef/3/
It appears to be a bug caused by Blend.toObject() not saving its class type, so Blend filter ends up without type: 'Blend' when serialized. To deserialize the object correctly, Fabric parses its type property, and when it doesn't find one for the serialized filter, it just abandons it.
Here's a patch you can use to fix this:
fabric.Image.filters.Blend.prototype.toObject = function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
color: this.color,
image: this.image,
mode: this.mode,
alpha: this.alpha
});
}
BaseFilter.prototype.toObject() does set the type property, so it makes sense to just extend Blend.prototype.toObject() from the object it returns.
P.S: the latest fabric.js 2.4+ doesn't have this issue so it's one more reason to upgrade.

how to implement complex models in aframe

I'm pretty new to aframe and the ECS-modeling technique, so I probably didn't fully grasp how the architecture should be used.
I want to model something like a robotic arm: in a simplified version that is a base, on top of that a rotator and the arm itself. The model is loaded from a single json-file and consist of several nested objects for the different parts.
How would something like this be implemented in aframe if I want to be able to control the different degrees of freedom independently (which means setting object.rotation-values on the different childs of the object itself)?
One thing I thought of was to implement the loading of the model-file as one component and each degree-of-freedom as a seperate component. So basically something like this:
<a-entity robot-model="..." base-rotation="123" arm-pitch="10" />
Or would it be a better way to use registerPrimitive for something like this?
My first take on it looks like this:
registerComponent('robot', {
schema: {type: 'asset'},
update() {
// - load and parse model using THREE.ObjectLoader
// - once ready, assign property this.parts with the various
// parts of the robot-arm
}
});
registerComponent('dof-1', {
schema: {type: 'number'},
dependencies: ['robot'],
init() {
this.robot = this.el.components.robot;
},
tick(t, dt) {
if (!this.robot.parts) { return; } // not ready yet
// update values (left out here: acceleration etc)
this.robot.parts.dof1.rotation.x = this.data;
}
});
// more parts / dof implemented likewise
I'm assuming you've already created and rigged a 3D model using software like Blender, Maya, or Cinema4D. If not, the article Animation from Blender to three.js is a good starting point.
Once you've done that, you can import the model into A-Frame with any format that supports skinning/rigging. THREE.ObjectLoader (.json) or THREE.GLTFLoader (.gltf) are good options, and there are already A-Frame components that wrap these loaders. Assuming you're using JSON and the object-model component from A-Frame Extras, you could do:
<a-entity object-model="src: url(my-model.json)"></a-entity>
At this point you should see a model in the scene, without having written any JavaScript, but it won't be animating yet. If you know what animation you want up front, you can create the animations in keyframes or morph targets using the same modeling software: Blender, Maya, or Cinema4D. Assuming you included the animations when you exported the model, you can use the animation-mixer component (also from A-Frame Extras) as follows:
<a-entity object-model="src: url(my-model.json)"
animation-mixer="clip: *;"></a-entity>
This will play all animations at once. You could use a clip name, instead of *, to play a specific animation.
If your animations need to be computed at runtime, and can't be baked into the model, you'll need to write a custom component. This gets complicated quickly, but the basics aren't too bad:
<a-entity object-model="src: url(my-model.json)"
custom-animation></a-entity>
And the JS:
AFRAME.registerComponent('custom-animation', {
tick: function (t, dt) {
var mesh = this.el.getObject3D('mesh');
// With complex models, you may need to loop over `mesh.children`
// in case the mesh you want to animate is a child of another
// object in your model file.
if (!mesh || !mesh.isSkinnedMesh) { return; }
mesh.traverse(function (node) {
if (node.isBone && node.name === 'arm') {
node.rotation.x += dt * Math.PI / 1000;
}
});
}
});

Three.js - collada model not loading when specifying a texture

I try to load a converted collada model (obj -> collada [opens without a problem in max, including working uvs]) with the three.js collada loader. The model was converted using assimp, an open source 3d model converter.
A thing I noticed is that the converted collada model has children inside children but I heard that would be no problem. However if I change the material to something with a texture, I get an error: "TypeError: uv2i is undefined".
As long as I do not use a texture the model loads.
https://dl.dropbox.com/u/2705276/bachelorShowcases/001/webGL_museum_wire.html
Model not loading when specifying a texture:
https://dl.dropbox.com/u/2705276/bachelorShowcases/001/webGL_museum.html
Is this a bug or am I doing something wrong?
function load( model ){
loader.load( 'https://dl.dropbox.com/u/2705276/bachelorShowcases/001/xerox404_webglCONV.dae', createScene1 );
}
function createScene1( geometry ) {
dae = geometry.scene;
mesh = dae.children[0].children[0];
mesh.material = new THREE.MeshPhongMaterial({map:THREE.ImageUtils.loadTexture('https://dl.dropbox.com/u/2705276/bachelorShowcases/001/xeroxD.png')});
}
If you check the console you'll see this error:
webGL_museum.html:461
Uncaught TypeError: Cannot read property 'u' of undefined three.js:17814
That basically means that your model doesn't have UVs. In order to use a texture with a model it needs to have UVs.

Resources