Scaling an object in three.js - three.js

I am getting
Matrix3.getInverse(): can't invert matrix, determinant is 0 three.js 3976
error when I am trying to scale a cube object.
var object = new.THREE.Mesh(geometry, material)
xScale = 0.1;
object.scale.x = object.scale.y = object.scale.z = xScale;
Could someone help me out of this.

Matrix3.getInverse(): can't invert matrix, determinant is 0 usually happens when either the scale.x, scale.y or scale.z are 0. Make sure you're not scaling the object to 0.

I think you may be trying to use a Matrix3 where a Matrix4 is required. At least in r61 of the three.js library, the line you refer to is pulling from the matrix array beyond index 8 (ie. a 16 element matrix vs. a 9 element).
If you need any advice beyond that provide some code and description to what your trying to achieve with the inverse matrix, good luck!

Related

Slant/Skew a Texture - Monogame

I am trying to Slant/Skew a texture to create some shadows for my game.
I have read over this helpful answer that shows this can be done by passing a matrix to spriteBatch.Begin().
Because my linear algebra skills are not very developed, I am having some troubles meeting my desired results. I am hoping to skew my shadow so it looks similar to the following. Where the shadow is slanted by an angle, but the bottom of the shadow lines up with the (feet in this case) bottom of the sprite.
I originally tied the skew matrix provided in the solution above:
Matrix skew = Matrix.Identity;
skew.M12 = (float)Math.Tan(MathHelper.ToRadians(36.87f));
But this ends up rotation the shadow against the world's origin. I see the solution also notes this, and provides the follow to rotate again the sprite.
Matrix myMatrix = Matrix.CreateTranslation(-100, -100, 0)
* Matrix.CreateScale(2f, 0.5f, 1f)
* Matrix.CreateTranslation(100, 100, 0);
Though I'm not sure where to apply this myMatrix Matrix. I have tried applying it to both the shadow sprite, the castingShadow sprite, and also multiplying them together and applying to the shadow with no luck.
I have also tried using other methods like Matrix.CreateRotationX(MathHelper.ToRadians(0.87f)) with no luck.
There is actually a Matrix.CreateShadow() method too, but it requires a Plane, which I have no semblance of in my game.
Can anyone can help me figure out the required Matrix for this slanting, or point me in the direction of some resources?
Thanks!
Okay, so I found a transform to use to get the desired slant.
Thanks to #David Gouveia and #AndreRussell from this post
Matrix matrix = Matrix.CreateRotationX(MathHelper.ToRadians(60)) *
Matrix.CreateRotationY(MathHelper.ToRadians(30)) *
Matrix.CreateScale(1,1,0);
EDIT:
So the above solution solved how I wanted to slant my texture, but had some weird positioning side effects. To address this, I ended up with a transform like the following:
Matrix slant = Matrix.CreateTranslation(-loc.X + angleX, -loc.Y, 0f) *
Matrix.CreateRotationX(MathHelper.ToRadians(angleX)) *
Matrix.CreateRotationY(MathHelper.ToRadians(30)) *
Matrix.CreateScale(1.4f, 1f, 0) *
Matrix.CreateTranslation(loc.X + angleX, loc.Y, 0f);
Where angleX was set based on the "sun" X position and loc vector is where I want the object and object's shadow to appear.

How to modify UV coordinates with three.js

I want to modify a JSON model's unwrap (UV coordinates) during runtime in order to move the texture over the surface of the geometry. I found faceVertexUvs in the Geometry class documentation. It contains one array, which is correct. That array contains a lot of elements, which I assume to be the UV coordinates for each vertex. Example code:
var uvs = mesh.geometry.faceVertexUvs[0];
console.log(uvs.length);
Gives me 4232 as output. So far so good. Now I would like to alter the u and v values, but the 4000+ elements of the array are strings ("1" through "4234"). I only found examples showing how to create an unwrap from scratch, in which case people push Vector2 data up into faceVertexUvs. So why am I not seeing Vector2 data in there?
Okay, I solved this one myself, hooray. I was searching for the wrong terms, because three.js makes this pretty simple. Instead of actually altering the unwrap (UV coordinates of the geometry), it is possible to set an offset on the texture itself:
texture.offset.y += 0.1;
For this to work with a seamless/tiling texture, we also have to tell three.js that the texture should wrap/repeat:
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
Source: Tunnel Effect Tutorial
Well, that was easy!

Matrix multiplication does not work in my vertex shader

Currently, I am calculating the World View Projection Matrix in my application instead of the GPU. I want to move this calculation to the GPU, but I am currently unable to do so.
Case 1 (see below) works very well, but case 2 doesn't and I have no idea what I've done wrong.
In my camera class, I calculate the View and the Projection matrices like this:
ViewMatrix = SharpDX.Matrix.LookAtLH(_cameraPosition, _lookAtPosition, SharpDX.Vector3.UnitY);
ProjectionMatrix = SharpDX.Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, renderForm.ClientSize.Width / (float)renderForm.ClientSize.Height, 0.1f, 500.0f);
Then, I calculate the World matrix for each of my models during the render process:
SharpDX.Matrix worldMatrix = SharpDX.Matrix.Translation(_position);
Case 1: Calculation of matrix in my application
When rendering a model, I calculate the World View Projection Matrix like this:
SharpDX.Matrix matrix = SharpDX.Matrix.Multiply(worldMatrix, camera.ViewMatrix);
matrix = SharpDX.Matrix.Multiply(matrix, camera.ProjectionMatrix);
matrix.Transpose();
And in my vertex shader, I calculate the final position of my vertices by calling:
output.pos = mul(input.pos, WVP);
And everything works fine!
Case 2: Calculation of matrix in HLSL
Instead of calculating anything in my application, I just write the three matrices World, View and Projection into my vertex shader's constant buffer and calculate everything in HLSL:
matrix mat = mul(World, View);
mat = mul(mat, Projection);
mat = transpose(mat);
output.pos = mul(input.pos, mat);
It does work. I don't see anything in my scene. So I assume some calculations were wrong. I checked my code several times.
Either, I am blind or stupid. What did I do wrong?
in hlsl you don't need to calculate the transpose. You shoul also use the float4x4, so it's easy to see which dimensions you use.
Your matrices just should look like:
float4x4 worldViewProj = mul(world, mul(view, proj));
float4 pos = mul(input.pos, worldViewProj);
Keep in mind that points are from type float4(x,y,z,1) and vectors are float4(x,y,z,0).
In linear algebra multiplication of a vector is
𝑝′=𝑀⋅𝑝
so you need the transpose for changing side of M
𝑝′𝑇=pT⋅𝑀𝑇 (the T means the transpose)
HLSL is a bit different.
For the easiest way, just multiply all matrices from left to right and then use the mul function with your vector on the left just as in my example above.
For more information read this: HLSL mul()
I used several days to experiment with the HLSL shaders and with my render functions. It turned out, that I transposed one matrix which I shouldn't have done. As a result, my whole scene was messed up. It was not much fun to debug, but it works now! :-)

LibGDX Matrix4 3d rotation problems given direction vector3

By now I am so confused that I'm not sure of my vector math anymore.. I have a Matrix4: MatrixA representing an objects (sensor cube) world transform. I want to place this object so that it's forward direction is pointing in the same direction as a given normalized Vector3: VecA . I also want to translate the objects (i.e. 4 units) in VecA's direction from a given point: VecB (the translation part works, using the same direction vector, VecA)
I have tried all the ways I can think of including rotate()+translate(), setToWorld(), setToLookAt(), setToRotation(), manually editing the values (column 3) of the Matrix4 (this gave the best results in terms of rotation but I get a skewed cube)
I know my direction vector (VecA) is OK. (by printing it's value and also visually confirming it by looking at the working translation using the same vector)
Can someone please tell me how I should do to achieve my desired results, thanks!
Assuming you're unrotated "forward direction" is (0,0,1), your unrotated "up direction" is (0,1,0) and you don't want to rotate the up direction (if possible), then something like this (untested code) should be what you need:
Vector3 vx = new Vector3(), vy = new Vector3(), vz = new Vector3();
Matrix4 m = new Matrix4();
...
vecB.set(vecA).scl(4.f); // if understand correctly, this is what you want
vz.set(vecA).nor();
vx.set(vz).crs(0, 1, 0).nor();
vy.set(vz).crs(vx).nor();
m.idt();
m.val[Matrix4.M00] = vx.x; m.val[Matrix4.M01] = vx.y; m.val[Matrix4.M02] = vx.z;
m.val[Matrix4.M10] = vy.x; m.val[Matrix4.M11] = vy.y; m.val[Matrix4.M12] = vy.z;
m.val[Matrix4.M20] = vz.x; m.val[Matrix4.M21] = vz.y; m.val[Matrix4.M22] = vz.z;
m.trn(vecB);
It is possible that you need to switch the crs arguments though (e.g. vy.set(vx).crs(vz).nor(), in case the rotation is upside-down). Alternatively you could use a Quaternion to specify the rotation and use m.set(vecB, rotationQuaternion);.

Setting the projectionMatrix of a Perspective Camera in Three.js

I'm trying to set the ProjectionMatrix of a Three.js Perspective Camera to match a projection Matrix I calculated with a different program.
So I set the camera's position and rotation like this:
self.camera.position.x = 0;
self.camera.position.y = 0;
self.camera.position.z = 142 ;
self.camera.rotation.x = 0.0;// -0.032
self.camera.rotation.y = 0.0;
self.camera.rotation.z = 0;
Next I created a 4x4 Matrix (called Matrix4 in Three.js) like this:
var projectionMatrix = new THREE.Matrix4(-1426.149, -145.7176, -523.0170, 225.07519, -42.40711, -1463.2367, -23.6839, 524.3322, -0.0174, -0.11928, -0.99270, 0.43826, 0, 0, 0, 1);
and changed the camera's projection Matrix entries like this:
for ( var i = 0; i < 16; i++) {
self.camera.projectionMatrix.elements[i] = projectionMatrix.elements[i];
}
when I now render the scene I just get a black screen and can't see any of the objects I inserted. Turning the angle of the Camera doesn't help either. I still can't see any objects.
If I insert a
self.camera.updateProjectionMatrix();
after setting the camera's projection Matrix to the values of my projectionMatrix the camera is set back to the original Position (x=0,y=0,z=142 and looking at the origin where I created some objects) and the values I set in the camera's matrix seem to have been overwritten. I checked that by printing the cameras projection Matrix to the console. If I do not call the updateProjectionMatrix() function the values stay as I set them.
Does somebody have an idea how to solve this problem?
If I do not call the updateProjectionMatrix() function the values stay as I set them.
Correct, updateProjectionMatrix() calculates those 16 numbers you pasted in your projection matrix based on a bunch of parameters. Those parameters are, the position and rotation you set above, plus the parameters you passed (or default) for the camera. (these actually make the matrixWorld and its inverse.
In case of a perspective camera, you don't have much - near, far, fov and aspect. Left,right,top,bottom are derived from these, with an orthographic camera you set them directly. These are then used to compose the projection matrix.
Scratch a pixel has a REALLY good tutorial on this subject. The next lesson on the openGL projection matrix is actually more relevant to WebGL. left right top and bottom are made from your FOV and your aspect ratio. Add near and far and you've got yourself a projection matrix.
Now, in order for this thing to work, you either have to know what you're doing, or get really lucky. Pasting these numbers from somewhere else and getting it to work is short of winning the lottery. Best case scenario, you can have your scale all wrong and clipping your scene. Worst case, you've mixed a completely different matrix, different XYZ convention, and there's no way you'll get it to work, or at least make sense.
Out of curiosity, what are you trying to do? Are you trying to match your camera to a camera from somewhere else?

Resources