Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

WebGL effort

Information, contacts and source code for ports to Linux, Windows, etc.

Moderators: winston, another_commander

Commander_X
---- E L I T E ----
---- E L I T E ----
Posts: 670
Joined: Sat Aug 09, 2014 4:16 pm

Re: WebGL effort

Post by Commander_X »

grondilu wrote:
Thanks. With this I may be able to render the Coriolis station. And if I have a Coriolis station and the ships, I can do a big part of the gameplay in space.
[...]
I'm very much confused by what happened to the 1.8+ cobra3. I need to think on it hard to understand what's wrong.
Well, while looking into the cobra3 issue, I tried to run your Perl script against the oolite_cobra3.dat, but it seems you're using a Regex class not known by "my" Perl (on Cygwin64).
You might expect harder texturing times with the Coriolis (which has 3 subentities) as opposed to Cobra3.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Commander_X wrote:
grondilu wrote:
Thanks. With this I may be able to render the Coriolis station. And if I have a Coriolis station and the ships, I can do a big part of the gameplay in space.
[...]
I'm very much confused by what happened to the 1.8+ cobra3. I need to think on it hard to understand what's wrong.
Well, while looking into the cobra3 issue, I tried to run your Perl script against the oolite_cobra3.dat, but it seems you're using a Regex class not known by "my" Perl (on Cygwin64).
You might expect harder texturing times with the Coriolis (which has 3 subentities) as opposed to Cobra3.
I had experimented a bit with the Coriolis and fusing the three parts should not be an issue. My main concern was the texture but your fragment shader will probably solve this.

I had fun writing this Perl 6 script but it's very slow for large meshes so I will re-write it in perl 5.

At some point I will have to add normals if I want to put light effects (and I do want to). But this makes me wonder : since there must be one normal per vertex, and normals are determined by faces, I have the feeling I will have to make sure no two faces share vertices. So the code I wrote was basically pointless : I can just make a new set of vertices from the faces (and I will always have exactly 3 times more vertices as I have faces).
Commander_X
---- E L I T E ----
---- E L I T E ----
Posts: 670
Joined: Sat Aug 09, 2014 4:16 pm

Re: WebGL effort

Post by Commander_X »

grondilu wrote:
I had fun writing this Perl 6 script but it's very slow for large meshes so I will re-write it in perl 5.

At some point I will have to add normals if I want to put light effects (and I do want to). But this makes me wonder : since there must be one normal per vertex, and normals are determined by faces, I have the feeling I will have to make sure no two faces share vertices. So the code I wrote was basically pointless : I can just make a new set of vertices from the faces (and I will always have exactly 3 times more vertices as I have faces).
Yup, "perl --version" gives me "This is perl 5[...]".
I guess you could also use one of the javascript OBJ loaders. This might be an incentive to have the Dat2Obj*.py scripts brought up-to-date with the new *.dat formats (maybe even including the multitexturing part).
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: WebGL effort

Post by cim »

Commander_X wrote:
The trick is the textures use alpha channel (I guess for emission or the sorts).
Yes. To halve the number of texture files needed, diffuse is on rgb, and greyscale emission is on a.
grondilu wrote:
I have the feeling I will have to make sure no two faces share vertices.
That shouldn't be necessary. (Unfortunately I can't give you any more useful info than that, since I don't understand that bit very well myself)
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

So I added keyboard controls (arrow keys) for pitch and roll with the Euler angles method, and as expected I encounter difficulties with large angles.

For instance if you pitch +90° so that your ship becomes vertical, then roll +90° so that you show its side, then pitching again does not rotate the ship in the expected axis (you get what would normally be a yaw).

If I spend some time thinking about it I will eventually figure it out, but I'm going to be lazy and ask you guys how I do this using quaternions.
User avatar
kanthoney
Commodore
Commodore
Posts: 281
Joined: Thu Nov 07, 2013 10:21 pm

Re: WebGL effort

Post by kanthoney »

My quaternions are a bit rusty, but I think the recipe goes like this. If you want to rotate by an angle t around a normalized vector with components (a,b,c), you create a quaternion:

q_rot = cos(t/2) + a.sin(t/2)i + b.sin(t/2)j + c.sin(t/2)k

if q_orig is as quaternion specifying the original orientation of the ship, the new orientation is calculated with the formula

q_new = q_rot.q_orig.(q_rot*)

where q_rot* is the complex conjugate of q_rot, i.e. with the i,j,k components turned negative.

To do a roll, you first have to find out where the roll axis is. For an unrotated ship, this will be the z-axis (probably the -z axis if memory serves), so q_rot would be cos(t/2) - sin(t/2)k. For a ship with orientation q_orig, you would first rotate -k by q_orig to find the rotation axis:

q_axis = q_orig.(-k).(q_orig*)

The rotation quaternion would be

q_rot = cos(t/2) + q_axis.sin(t/2)

and the new orientation would be

q_new = q_rot.q_orig.(q_rot*)

To do a pitch you would replace -k with i, and for a yaw you'd replace -k with j.

Something like that anyway!
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Well, I failed but I get a weird behavior that is I think worth of showing, so I push the attempt anyway.

Pick the "Quaternions" option instead of "Euler" at the bottom.

http://grondilu.github.io/oolite/ships.html
User avatar
kanthoney
Commodore
Commodore
Posts: 281
Joined: Thu Nov 07, 2013 10:21 pm

Re: WebGL effort

Post by kanthoney »

I think you're muddling your methods quite a bit, which isn't helping. Firstly, in these lines:

Code: Select all

var M = mat4.create();
mat4.fromQuat(M, Q);
mat4.multiply(mvMatrix, mvMatrix, M);
quat.invert(Q, Q);
mat4.fromQuat(M, Q);
mat4.multiply(mvMatrix, M, mvMatrix);
the first three lines are OK - you're calculating a rotation matrix from a quaternion, and then multiplying the model view matrix by it. But then you're multiplying by the inverse matrix in the second three lines. You don't need to do that, as the fromQuat effectively does the multiplying-by-the-conjugate bit of the quaternion recipe for you.

So if you remove the final three lines of the above, you get rid of the weird effect, but you get back to the problem you were having with the Euler angles. That's because you're calculating the quaternion from the Euler angles, so you get the same problem. I'd try storing the orientation as a quaternion and manipulating that.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Well, I've finally managed to do it but that was painful. And to be honest I still don't understand everything.

The code that worked was:

var scale = 2000;
quat.multiply(Q, Q, [Math.sin(Pitch/scale), 0, 0, Math.cos(Pitch/scale)]);
quat.multiply(Q, Q, [ 0, Math.sin(Yaw/scale), 0, Math.cos(Yaw/scale)]);
quat.multiply(Q, Q, [ 0, 0, Math.sin(Roll/scale), Math.cos(Roll/scale)]);

mat4.fromRotationTranslation(mvMatrix, Q, [0.0, 0.0, -200.0]);


That was after I realized I should store the orientation of the ship in a global quaternion variable.

Before that I tried something which I thought was the same :

var scale = 2000;
quat.multiply(Q, Q, [Math.sin(Pitch/scale), 0, 0, Math.cos(Pitch/scale)]);
quat.multiply(Q, Q, [ 0, Math.sin(Yaw/scale), 0, Math.cos(Yaw/scale)]);
quat.multiply(Q, Q, [ 0, 0, Math.sin(Roll/scale), Math.cos(Roll/scale)]);

mat4.fromQuat(mvMatrix, Q);
mat4.translate(mvMatrix, [0.0, 0.0, 0.0, -200.0];


But no, apparently it's different. The center of rotation keeps being the origin, not the ship.
User avatar
Day
---- E L I T E ----
---- E L I T E ----
Posts: 545
Joined: Tue Mar 03, 2015 11:35 am
Location: Paris

Re: WebGL effort

Post by Day »

kanthoney wrote:
My quaternions are a bit rusty
Some javascript libraries allow to hide the quaternion work, and generally to manipulate easily 3D models in webgl.
It might be useful here.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Pitch and roll indicators now :

Image

The HUD is a superimosed 2D canvas. It's quite a natural choice since the HUD is supposed 2D graphics.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

Well, I have translated the mesh converter script in Perl 5, made an adjustable viewing distance for each ship, added some information messages during image loading, and imported the Mesh for the Coriolis:

Image

It does not look too great, unfortunately. But that's OK for a first try, I guess.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

There was a silly mistake in my Perl script. The Coriolis station looks much better now :

Image

Notice that I had to adjust the Z component of the dock by 500 meters. Not sure why it was not connected to the rest of the model.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: WebGL effort

Post by cim »

grondilu wrote:
Notice that I had to adjust the Z component of the dock by 500 meters. Not sure why it was not connected to the rest of the model.
Subentities will often be offset relative to the parent entity. From shipdata.plist for the coriolis:

Code: Select all

subentities = 
		( 
			{ 
				subentity_key = "oolite_coriolis_faceplate"; 
				orientation = (1, 0, 0, 0); 
				position = (0, 0, 0);
				is_dock = false;						
			},
			{ 
				subentity_key = "oolite_coriolis_tris"; 
				orientation = (1, 0, 0, 0); 
				position = (0, 0, 0); 
				is_dock = false;
			},
			{ 
				subentity_key = "oolite_coriolis_dock"; 
				orientation = (1, 0, 0, 0);
				position = (0, 0, 500.2561);
				is_dock = true; 
			},
Note the non-zero position on the dock subentity.

There are various internal implementation reasons which require docks to be subentities, and also generally mean that they will be offset subentities.

Subentities can also be rotated relative to the parent model with the orientation quaternion.
grondilu
Competent
Competent
Posts: 48
Joined: Sat Jun 27, 2015 2:48 pm

Re: WebGL effort

Post by grondilu »

cim wrote:
Subentities will often be offset relative to the parent entity. From shipdata.plist for the coriolis:
If I want to make progress at some point I will have to parse this file. I deplore the choice of the plist format. Any chance there is a convertor to JSON?
Post Reply