I've been working for some time on making a 3D first person camera in p5.js for games and random projects, but I've been having some trouble.
For some time now I've been using a single y-rotation matrix with my projects to allow the player to look around, but I've felt like having an upgrade recently, so I decided to use x and y rotation matrices for my camera code. I was able to botch together a system that kind of worked by dividing both calculated z values, but there were some issues, not to mention that's not how rotation matrices work. I recently tried doing a proper implementation, but I've come across some issues.
I've been using this: camera(0, 0, 0, -200*sin(rot.y), -200*sin(rot.x), (200*cos(rot.x)) + (200*cos(rot.y)), 0, 1, 0); as my test camera code, which in theory would work, but in an actual setting, it doesn't for some reason, as you can see here. Right now if you look around too far it will randomly spaz out and mess up the way you're looking.
I also can confirm that I am using the correct formulas as here. I used the (almost) exact same code for calculating the values, and it looks completely fine.
Is there any weird trick to using the p5.js camera or is this some error that needs to be fixed?
You actually don't have the correct formulas. The example you showed uses orbitControl(), not camera. It also doesn't have two different angles it's rotating through.
The middle 3 coordinates of camera() define the point toward which the camera is pointing. That means that you want that point to move the same way you want the focus of the camera to move. It might help to draw a box at that point like this (in your original):
push();
translate(-200*sin(rot.y), -200*sin(rot.x), (200*cos(rot.x)) + (200*cos(rot.y)));
box(50);
pop();
You'll notice that the box is not always the same distance from the camera. It stays on a torus whose major and minor radii are both 200. What you want is a sphere with radius 200 (really it can have any radius).
The way you define these three coordinates depends on how you want the user's interactions to be. Here's one way:
camera(0, 0, 0,
cos(rot.x) * cos(rot.y),
cos(rot.x) * sin(rot.y),
sin(rot.x),
0, 0, 1);
This points the camera based on latitude and longitude, with the north pole on the positive Z axis. Moving the mouse right and left affects the longitude, and up and down affects the latitude.
Related
Im trying to create an effect where I have multiple images/meshes on the same sine wave. I can distort all separately, but of course they are not in sync.
In the vertex shader I have this line for the simple distortion:
pos.z += sin(pos.y);
My Idea would be to make the sin wave independent from the pos.y value and replace it with something like the current position y in the height of all of my images.
My other Idea would be to have only one mesh and paste every image on it, but I am not sure if it is a good practice or if that would work at all.
I would be greatful for any suggestion on how to implement this.
Thanks!
Yes, this is possible. See this example, which shows 4 adjacent grids in sync. You have to adjust certain values to put them all in sync. At present, I had been able to do so only in directions of 45 degree increments. But you can use multiple waves of varying magnitudes and frequency.
The example was created using three.js code to perform the animation, but I have been able to replicate some of this using a shader.
Let me know if you still need help.
Here is an example of Goraud interpolation and a Lambertian reflection model from a textbook.
https://jsfiddle.net/zhenghaohe/r73knp0h/6/
However in the textbook there is a stupid error, in this book it says the code should contain this following line, when in fact it does not.
vec3 light = vec3(uModelViewMatrix * vec4(uLightDirection, 0.0));
The weird thing is the example still seems to work.
I am aware of that the sphere is rotating because
mat4.rotate(modelViewMatrix, modelViewMatrix, angle * Math.PI / 180, [0, 1, 0]);
However it seems to me that the light is also moving with the sphere. But in the code I cannot find how the light is being moved around.
Can someone please point me to the code where we also rotate the light?
The light does not rotate, it is fixed in a static position and direction. The problem here is you do not seem to understand what a normal is and how it is used in computer graphics.
A computer model is a series of "vertices" that connect to form "faces" (usually triangles). When "realistic" light is introduced into a scene an additional piece of information is necessary to determine how it should interact with each face of the model, this is called a "normal." A normal is a directional vector that generally forms a line perpendicular to a face, but it does not have to which will become important for your problem. This normal is used to compute how light interacts with that surface.
So you have three sets of data: The vertices, the indicies (how the verticies come together to form faces), and the normals (computed automatically in your example). The problem arises when you begin to make transformations to the model (like rotation) but do not perform similar transformations to the normals that were computed before the transformation.
Let's visualize this... say we have the following pyramid with one of it's normals drawn to illustrate the problem:
Now when we start to rotate the pyramid, but we leave the normals directions unchanged we see that the angle between the normal and the face begins to change.
For things to work as expected we need to also rotate the normals so that the angle relative to the face does not change.
The angle of the light relative to the surface normal is what dictates how the surface is shaded by the light. When you're rotating the model the normals begin pointing in "random" directions, this messes with the light computation and it appears as if the light is rotating, but it is not.
Obviously this is a very watered down explanation of what is happening, but it should give you a basic understanding of what a normal is and why you need to apply transformations to them as well.
I'm kinda new in Three js and I've been struggling with this for a while.
I have a 3d model facing a certain direction.
There is also a sphere around it and before moving the mesh, I want to animate it's rotation so it will face specified sphere.
So far I managed to get the angle of rotation but I suppose that is not the way to go
this is what I use for rotating the object towards a specified point:
if(movementTarget) { playerModel.lookAt(movementTarget); }
and this is the content of the
movementTarget = {x:154,y:55,z:35};
seems like the model is not actually orienting towards the sphere, but an empty spot, not sure what is the issue
I have managed to solve the issue, the coordinate system had a general variable which amplified the distance between the objects, by calling lookAt() function, the camera was oriented in the correct direction, but since the corrdinates Were not multiplied since they came straight from the server.
The short story: I am trying to use THREE.TrackballControls to move the camera, but the (upside-down) x-z plane is where the x-y plane should be. Can anyone help?
The long story: I've been trying to add device orientation controls to a project. I have already used the THREE.TrackballControls to move the camera when mouse and touch are being used, and the direction the camera points feeds into other functionality. I am using v69 of three.js.
So, I have been looking into using THREE.DeviceOrientationControls to enable device orientation. Specifically, what I'm after is for rotation to be in the x-y plane when the device is upright in front of me and I turn around. Or in other words, when the device is face up on the table it is looking in the -ve z-direction, and when upside down it it looking in the +ve z-direction. Sounds fairly straightforward, right?
There are plenty of examples around to follow, but I seem to be stuck with axes incorrectly orientated, i.e. what should be my x-y plane is coming out as the x-z plane, but upside-down. I created a test page based on an example with a BoxGeometry cube I found, and then added red, yellow and blue spheres to the middle of the faces that corresponded to the +ve x-, y-, and z-directions respectively, and then pale versions of the same coloured spheres for the corresponding -ve directions. Testing this on an iPad confirmed that the scene axes and the real world axes were not lining up.
I have spent a bit of time trying to get to grips with how this Object works, and the main sticking point is in the function returned by setObjectQuaternion() which does the tricky bit:
...
return function (quaternion, alpha, beta, gamma, orient) {
euler.set(beta, alpha, -gamma, 'YXZ'); // 'ZXY' for the device, but 'YXZ' for us
quaternion.setFromEuler(euler); // orient the device
quaternion.multiply(q1); // camera looks out the back of the device, not the top
quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation
}
...
where q1 is quaternion for a -pi/2 rotation around the x-axis, and zee is a unit z-axis vector.
I set up a jsfiddle here to help me debug this, but it wasn't rendering correctly on the iPad itself, so I had to add in some faking of orientation events, and plenty of logging, and continue on a normal desktop + console. This jsfiddle goes through each of the 6 basic orientations and sees whether the camera is looking in the direction I expect.
(Initially it would seem that a pi/2 rotation around the x-axis is what is required, but removing the quaternion.multiply(q1) doesn't fix it - I haven't even started looking at non-zero screen orientations yet.)
Ultimately, I'd like to make this more like the TrackballControls/OrbitControls with a target point that the camera always looks at (unless panned) and rotates around, once I've figured this "simple" stuff out.
Anybody have any ideas how I can orientate my camera properly?
Ok, so... here's what I'm trying to do. In HTML/JS. With a math knowledge that would embarrass a twelve-year old.
With, say, 20 checkboxes on a page, the user picks.. five of them. A circle then appears on the page (I'd anticipate using one of the canvas libraries like Raphael) with their five answers arranged around it. So that's the first thing I don't know how to do; split a circle into x equal segments. Strange, foreign terms like "cos" and "sin" are looming on the horizon.
But then it gets even more fun: the user can click a point on the circle. And that point is translated into some sort of percentage value for each of the segments. So if the user checks Happy, Grumpy, Sneezy, Dopey and Bashful, and clicks the circle, I can tell them that they're 37% Happy, 42% Dopey and 21% Sneezy.
The best analogy is probably a colour-picker wheel, but I can't find any JS ones that I could repurpose. A pie chart is close - and there's a nice Raphael demo - but I've got a feeling that the fixed boundaries of a pie chart segment is going to take me down the wrong route for estimating percentage positions within the circle as a whole.
So, given my vague and poorly thought out request, and the noticeable absence of any "here's what I've tried so far" code - because I don't have the foggiest where to even start, apart from high school trigonometry books, can anyone suggest any code libraries or snippets that might get me at least pointing in the right direction?
Thanks :)
========================
Edit :
Wow, thanks for all the answers. I'll try to refine the question/s a bit:
I'm going to need to draw a circle with x number of points arranged equally around its circumference. The number of points will correlate to the number of checkboxes that the user checked.
That's the first bit I'm stuck on: I reckon that I can draw a circle, with dimensions and at a position on the page of my own choosing, (using Raphael or similar canvas library) but how can I calculate what the x/y pixel coordinates of those points should be on the circle circumference?
The second bit: the user then clicks anywhere in the circle. I guess what I'd do is calculate how far each of the circumference points are from that user click point - I'm not sure how to do that, apart from a vague suspicion it involves imaginary triangles - and then how much of a total distance each of those distances are. That last bit, at least, I can manage.
Actually, this is starting to make sense. I'm still not sure how the trig stuff works but it's amazing what typing your problem out so that strangers will understand it can do to help your own understanding...
You need to revise your question to explain more clearly what you are trying to do. In the meantime, I can give you the following information that may help you get started.
First of all, you'll need to know the locations of the five checkboxes that the user selects. In order to do this, the jQuery library offers some convenient functions such as $.position and $.offset.
Your question does not make clear exactly how the circle you want to draw is positioned in relation to the five checkboxes that the user clicks. As for actually drawing the circle, you may want to use something like the HTML5 canvas element. I've not yet used it myself, so I can't tell you much about it.
You might want to try asking another question on StackOverflow about how to draw a circle on your web page once you've computed the center and radius of the circle.
As for doing the math about the circle, you need to know that a circle can be parameterized on an x-y plane by the following equations:
x = x0 + r cos(theta)
y = y0 + r sin(theta)
where (x0,y0) is the center of the circle, r is the radius of the circle, and theta ranges over 0 to 2*Pi radians (0 to 360 degrees)
Let us know more about what you're doing and we can give you some more specific information.