setAttribute for multi attribute component not working for vec3 - three.js

I am trying to add a multi-attribute component to an entity through the following code -
within a-frame scene -
<a-entity id="hornets"></a-entity>
within controller -
var hornets = document.querySelector('#hornets');
hornets.setAttribute('crtmodelcopy', {id: 'ball', jitter: 5 1.2 0.4, modelCenter: 2 0.5 -50, src:'#hornet'});
The code for the component is as follows -
AFRAME.registerComponent('crtmodelcopy', {
schema: {
id: {type:'string'},
jitter: {type:'vec3'},
modelCenter: {type:'vec3'},
src: {type:'string'}
},
init: function() {
......
}
But, I get the following error in console -
Uncaught SyntaxError: Unexpected number
I am unable to understand what I am doing wrong here. I have tried other combinations but to no avail. In some cases the component gets attached without any attributes. I think the problem is due to jitter and modelCenter attributes being vec3 fields so I need to pass the data also in the same format.
Could someone kindly help?
Thanks,
Niraj

Actually you're not passing a vec3, just three numbers which are an unexpected value, because the parser expects one vector.
Either pass a vec3:
setAttribute("test", {"jitter": new THREE.Vector3( 0, 1, 0 )})
or a string version of a vector:
setAttribute("test", {"jitter": "0 1 0"})
Check it out here. The console shows that both vectors are properly passed into the update function.

Related

Changing anisotropy after render do not work

I have problem with updating THREE above version 137 - If I change anisotropy after an object was rendered, it breaks the material on the object.
For example, let's use from three.js examples webgl_loader_texture_tga.html. Now let's add into init():
scene.background = new THREE.Color()
window.setTimeout( () => {
mesh2.material.map.anisotropy = 16;
mesh2.material.map.needsUpdate = true;
}, 1000 );
After timeout runs, object changes into black and we get these warnings to the console:
[.WebGL-00005420002AC600] GL_INVALID_OPERATION: Level of detail outside of range.
[.WebGL-00005420002AC600] GL_INVALID_OPERATION: Texture format does not support mipmap generation.
EDIT:
Live example can be found here: https://codepen.io/kajbo/pen/mdpwybO
Please notice that if you change THREE version to 137 or below everything works as expected.
This is actually a bug in three.js. I have filed a PR at GitHub to solve this issue: https://github.com/mrdoob/three.js/pull/23808

InstancedBufferGeometry.copy error in three.js

I am running a three.js example code, its three.js version is 0.124.
createObj() {
const geometry = new THREE.InstancedBufferGeometry();
const baseGeometry = new THREE.BoxGeometry(2, 2, 20, 2, 2, 6);
// Copy attributes of the base Geometry to the instancing Geometry
geometry.copy(baseGeometry);
}
when the code is running in 'geometry.copy(baseGeometry);', an error is popping up as showed as
TypeError: Cannot read properties of undefined (reading 'clone')
at InstancedBufferGeometry.copy (three.module.js?cf64:10935)
at InstancedBufferGeometry.copy (three.module.js?cf64:40628)
at createObj (Clouds.js?d048:24)
InstancedBufferGeometry.copy() only accepts another InstancedBufferGeometry object as the argument. You're trying to pass a legacy Geometry object (THREE.Geometry was part of the core up until r125, and you're using r124), so it breaks when performing that method when it notices that it's missing all the instancing properties.
See here in the docs for using the copy() method

three.js - cannot read property "y" of undefined

thank you for your help, dumb newbie question…
Working with a proven example - after dragging a cube - getting this error when trying to log the position.y value of an item in an array.
At line 88:
console.log("position.y = " + this.objects.position.y);
I’ve tried many variants on this of course - thank you in advance
EDIT (working link):
https://codepen.io/ken-thomas/pen/rQayYg
this.objects is an array of 200 or so meshes.
You need to pick which one you actually want to log the position of.
e.g:
this.objects[0].position.y
However, the dragend function gives you event data, one of the keys being the mesh you moved (event.object). So your code should look like this:
dragControls.addEventListener('dragend', (event) => {
console.log('position.y = ', event.object.position.y);
});
Working codepen - https://codepen.io/danlong/pen/EOaRBw

Draw a shape when an input changes

I am having a blast learning electron/node.js. I am trying to use paper.js to "encode" a string into an image, sort of...
I am using a "paperscript" file like this:
<script type="text/paperscript" src="mainCanvas.js" canvas="mainCanvas">
Basically, I am looking at how I can wire up events from say, an input to the paper context.
What I would like is or whenever the target input changes ($("#input").on("change"...)) for something (the something is not the issue here) to happen.
I wiring up the event directly in the paperscript file:
$("#mainInput").on("change", function() {
path.moveTo(50, 25);
})
But that did not work. Reading the documentation, it seems the context should have access to any global objects.
Can someone point me in the right direction?
I don't know exactly where your problem is, but here is a working example demonstrating how it can be done.
// draw square
var square = new Path.RegularPolygon({
center : view.center,
radius : 50,
sides : 4,
fillColor : 'orange',
applyMatrix: false
});
// on input change
$('#input').change(function ()
{
// rotate it accordingly to input value
square.rotation = this.value;
});

ThreeJS get uniform values for running material

I added an object with a MeshPhongMaterial to my scene. I want to spy on the uniforms that Three is setting on the object. I thought it would be as simple as obj.uniforms.uniformName, but that doesn't actually exist. Is there a simple way to get the runtime uniforms Three is setting?
What I'm after is the uniform names and their values.
The method I came up with requires a double loop. The only thing I can see on a running material that's useful is material.uniformsList which is a list of WebGLUniformLocations and values, but no names. There is also material.program.uniforms which is a key value store of names to WebGLUniformLocations. It seems like you can zip the two together to get a uniform list, but is there a better way?
let builtUniforms = {};
// For every uniform in the array, look for its location in the program
// uniforms to get the name
for( x = 0; uniform = object.material.uniformsList[ x++ ]; ) {
// uniform is [ { type, value }, WebGLUniformLocation ] but no name :(
for( uniformName in object.material.program.uniforms ) {
// If the WebGLUniformLocations match up, we've found the name
if( object.material.program.uniforms[ uniformName ] === uniform[ 1 ] ) {
builtUniforms[ uniformName ] = {
value: uniform[ 0 ].value,
name: uniformName
};
break;
}
}
}
Is there a more straightforward way to get the uniform names and values from a Three.Material?
Will the uniformsList or program.uniforms ever change? Do I need to build this object once per render loop, or can I build it once and resuse it?
Three stores the key value store you're looking for in material.__webglShader.uniforms
Also look in THREE.UniformsLib
and also THREE.ShaderLib - e.g. THREE.ShaderLib.phong
these contain the templates for built-in uniforms and also the shaders, like MeshPhongMaterial, which use them.

Resources