UPDATE (27 JUL 2025)
I finally figured out the math for a circle pursuit - where the enemy is on your tail and is trying to stay there while you turn. Here is the latest program, which combines the old Intercept routine (where the target is basically flying straight) with a new circle override (where the target is turning). I still need to make this handle vertical loops and all the various other aspects of air combat, such as the initial engagement.
very cool. of course since you mentioned vertical loops, the second thing I tried (after circle engagement) was a vertical loop, and I see the gimbal locking issue. Wondering if youâre using quaternions to compute these rotations? Imo it simplifies a lot of the math you have to do vs using Eulers, and gets around the gimbal locking problems.. allows better interpolation etcâŚ
I use a âpitch planeâ method to compute pitch values which eliminates gimbal lock problems.. (See this example) I compute pitch changes along the pitch plane and then convert the results to the vertical plane, taking into account pitch plane pitch and pitch plane bank. Fortunately, three.js makes this easy.
If you try to compute the impact of pitch changes directly on the vertical plane, you run into the problem that, at the top of the loop, the same change in aircraft pitch (relative to the pilot), has an increasingly smaller impact on pitch angle, eventually becoming immeasurably small.
great visualization.. thank you ![]()
I have completed the animation sequence for the plane handler.
When you start, he is just finishing the signal for âremove chocksâ (arms waving) and proceeding to the signal for âbrakes onâ (two arms up). (You donât have to do anything here since you are locked to the carrier.) Then he transitions to one hand in the air, waiting for you to start your run-up (the throttle is disabled before then). If you increase the throttle, he will start the ârun upâ signal (hand rotating) for a few seconds - giving you time to increase to full throttle. He will then proceed to the âtake-offâ animation and your plane will be unlocked from the carrier.
This sequence allows you to choose when to start your run-up, but does not allow you to take-off until the full animation sequence is complete. Of course, you can screw up by trying to take off at less than full throttle - but that one is on you. ![]()
Great news!
Thanks to Attila Schroeder, I now have an Ocean module that is a one-pass version of his full-featured Ocean program. The previous Ocean module used only Texture shaders. This new Ocean module uses Compute shaders, which are much faster and available only in WebGPU. He also added a few tricks to make things run faster. As a result, I have been able to double the number of ocean vertices which adds significantly more resolution to the waves.
Please let me know if you have any trouble running this new and improved version (it should run at 60 fps).
When you are on the carrier deck at the beginning of the FM2 flight demo, press âvâ to look around at the waves. After take-off press âaâ to use autopilot, so that you can safely look around and see how the new ocean looks as you climb.
As before, you can easily use this module in your own games since the results can be used with standard three.js materials and flat plane geometries.
UPDATE (11 Oct 2025)
Major change to islands/mountains. We previously used transparent textures and floated the island above water to create detailed shoreline and to avoid z-fighting. However, this created gaps where the bumpmap did not match the texture. We have now eliminated the transparent textures, extended the shorelines and sank the islands in the ocean. This has eliminated gaps and you can see the waves lapping against the islands. Where we use Giaros Island as a mountain, we are sinking the mountain into the land. See this page for a more detailed discussion of what we are now doing using Blender 4.5. Here is what Giaros Island and the Homebase Island now look like (I couldnât resist adding a small âtramp steamerâ to the latter).
Error fixes:
- FM2 and Pup now stop completely after landing
- Eliminated annoying TimeStamp error notices (fingers crossed)
- Fixed fatal shadow errors when switching views while in motion on ground
- Adjusted shadow bias
Happy Holidays!
Here are the major updates I have made over the past 2 months.
All versions have been updated to r182.
I have been working on improving the appearance of trees which appear in the Sopwith Pup and Huey helicopter demos. The ultimate goal is to be able to display large numbers of realistic trees at 60 fps.
I have also improved the cockpit shadows in the FM2 demo by modifying the cockpit view to include a second directional light with a small working area and trimming the near value of the original directional light to avoid conflicts. The difference in appearance is pretty amazing.
The old shadows (left) are a black blob. The new shadows show the canopy framework.
I am working on a more detailed description of the changes to cockpit shadows for others who might be facing the same challenges.
It appears you are trying to load that program on an i-phone? While that program is not one of the flight demos, the program uses the WebGPU ocean module (an iFFT ocean wave generator) which, based on my experience, does not currently work with iOS. (As far as I can tell, the WebGL version of the ocean module also does not work with iOS.)
The flight demos themselves are listed at the beginning of the original post and are designed to work with a mouse on something larger that an i-phone. The first demo uses the ocean module and probably wonât work on an iPad or Mac. But the other two, the Sopwith Pup and the Huey helicopter, should work since they donât use the ocean module.
If you donât have access to a mouse but want to see the airplane flight demos in action, you can use the following trick. Hold + to increase the throttle. Toggle âAâ to engage the autopilot. You can now use the arrow keys to perform basic navigation (no loops or inverted flight though).
Ah yeah Ocean and Ocean4 are both not working on my iPhone. (The Ocean3 link on the iFFT Ocean page is 404).
Have you checked what may be issue? I see no errors or logs in the console.
As for controls and small screens, thatâs icing on the cake, easy compared to the rest of what you made. Just use pointer events instead of mouse events (pointerdown, pointermove, etc).
Iâm guessing thereâs a fix for the ocean stuff, but until then it could fall back to something simpler perhaps!
I put all old versions of various modules into the xtra_perm directory of my GitHub Repo. That includes the Homebase Island demo and demos using the WebGL Ocean3 module (e.g. sdem_ocean3_gl2). They are currently updated to at least r180.
I had not worried about making the flight demos work with iOS because iOS was not compatible with WebGPU. However, I now understand that, about this time last year, Apple released iOS version 18.2 which is compatible with WebGPU. And I now see that many of the three.js WebGPU demos work on my iPhone. So I will see if I can figure out how to make my programs work with iOS. I would not recommend using the flight demos with an iPhone, due to limited screen size. But they could work fine with an iPad or Mac.
Let me know if you have any suggestions regarding changes which I need to make to my programs to make them compatible with iOS.
Update (Dec 30)
This is going to be a bit of a slog.
Apparently, iOS devices may have problems with textures of a size greater than 2048 and it would seem that, on an iphone, a lot of textures sizes should be reduced anyways due to small screen size.
My non-ocean demos appear to work fine. The WebGPU TSL particle emitter is no longer causing problems like it did before - so that is an improvement.
And I have removed all webkit references from my style sheets. I assume they are now obsolete.
But none of the ocean modules appear to work with iOS, not the WebGL version, or the WebGPU version which does not use compute shaders or the WebGPU version that does use compute shaders. Oddly, in the past few years, one iOS version displayed the WebGL ocean correctly. However, that was âfixedâ with the next iOS version and has not happened since. I will keep trying things to see if I can identify the problem.
I use ârepeatâ with the ground textures to achieve a resolution of 1 pixel = 1/2 foot. Also, I designed the plowed field texturesto show the true spacing between plowed lines (a couple of feet).
At low altitude, this level of detail makes landing easier. However, as you climb, the detail quickly vanishes and begins to look like a solid color. This is the same problem I faced with ocean waves. They looked fine at low altitude, but became a solid blue color as you climbed.
This is an inherent challenge with flight simulations, to make things look interesting at different altitudes. In the case of the the ocean, I was able to take advantage of the fact that ocean color varies.
I decided to try a similar approach with the land. If you look at a field from the air, you will see the the fields have all kinds of variations in color. There are many causes: (1) differences in the color of the soil; (2) features like rivers, ponds or paths; and (3) marks made by equipment when they plowed the field.
So what I did was to use Google Maps to find a defined pattern that I could use for a plowed field. I then converted the result to a black and white image which I then used as a âdiffuse text multiplierâ. Here is the code I used to create materials for the nearest grids:
if (n < 2) { // If texture is dirt or a meadow, use this multiplier
gt0_.G0MPtr[n] = new MeshLambertNodeMaterial({ // save material
colorNode: texture(DatTxt).mul(texture(grd_.DfT[0])), // <= basic field texture
});
}
else { // If texture is plowed ground, use this multiplier
gt0_.G0MPtr[n] = new MeshLambertNodeMaterial({ // save material
colorNode: texture(DatTxt).mul(texture(grd_.DfT[1])), // <= plowed field texture
});
}
For the more distant grids, I simply multiplied them by a value (0.85) designed to make the brightness of the outer grids match the brightness (or darkness) of the nearest grids.
Also, because the overall tendency was to make everything darker, I increased the intensity of the sunlight from 3 to 4.
Since the contrast is a little paler that I like, I will be experimenting with increasing the contrast of the black and white image for plowed fields to make it even more visible.
Hoipefully, this will be helpful to other flight sim creators.
[Addition]
One important point to note in all of this is that you can combine repeated materials with a non-repeated multiplier.
I have been watching YouTube videos of Arma pilots doing crazy stunts in helicopters and thought that would be fun to try to simulate. So I have added a new helicopter demo (MD500 - link added to original post) that permits the pilot to perform stunts like loops and rolls (with enough altitude). I still need to add some aids and assists and some targets to shoot at. But I thought you all might enjoy seeing what has been accomplished.
Use the mouse-wheel (or Q/E) to increase/decrease power, the mouse to change direction and the mouse buttons to yaw. Press O to toggle sound. Note that, unlike an airplane, pulling back does not increase the rate of turn or climb, but causes the helicopter to slow down. So, as you are turning, keep the helicopter tilted forward. (Note that, as you turn, you may need to add power or slow down since you are losing some lift in the bank - it is easiest to just fly at 100% power.) For climbs, you will have to reduce forward tilt to direct more thrust downward. You only need to climb to about 250ft to start looping and rolling safely. When you roll, you will need to pull back on the mouse as you roll inverted. (I may add an assist to keep the nose level when rolling.) The last 1/2 of the loop needs to be smoother, but can be accomplished.
The main blades are now animated to tilt
The power settings have worked out quite well:
85% power or above will lift the helicopter off the ground
80% power will hold you in a level hover
75% power will allow you to make a gentle landing. Pitch the helicopter back to slow forward speed and the use pitch and bank to keep the helicopter centered as you slowly drop to a landing.
For level steep turns, you will probably need about 90% power, decreasing to 85% for shallow turns.
For max climb, increase power to 100% and go to mostly level flight (just like an airplane loses forward speed as it climbs).
ADDITION (Mar 6)
I have now added a virtual cockpit view (press âvâ to toggle). I am still adding instruments and pilot animations, so it is not done yet. But you can still get the sensation of what it is like to pilot a helicopter.
The instrument panel is essentially complete and there are enough working instruments to allow you to land the helicopter while in cockpit view.
- To slow down, tilt the helicopter back slightly and watch the airspeed indicator (upper left). When the needle approaches straight up you are approaching a hover. Look at the outside terrain to confirm.
- To descend, reduce the throttle and watch the altimeter (3rd from left) and the vertical speed indicator (below the altimeter). When you are descending, the needle on the vertical speed indicator (VSI) will be pointing down and the needle on the altimeter will be moving counterclockwise. As the altimeter shows that you are almost at ground level, use the throttle and VSI to slow your rate of descent. You can also look at the terrain and, if you are facing SE, your shadow.
An expert pilot, of course, does both things simultaneously.
I am still working on getting the helicopter to easily perform a split-S. This is something the pilots in Arma do - but not something you would do in a real helicopter because of stress. I think it should work aerodynamically (which is what I wanted to test with this model), so there is probably something in the vertical thrust vector that I need to fix.
ADDITION (Mar 11)
The looping problem is solved. I had added instructions which (somewhat artificially) kept the helicopter pointed in the direction of flight. However, the equations went sideways (literally) when the helicopter went vertical in a loop.
Instead, I am using a âweather-vaningâ subroutine which causes the helicopter to point more in the direction of flight as speed increases (like an arrow). This more accurately reflects the behavior of a helicopter (as confirmed by my limited personal experience in flying a helicopter), but adds some challenge to the simulation.
Unlike an airplane where thrust pulls the airplane generally in the direction of flight, a helicopter is balanced on a column of air, the direction of which can changes without regard to the direction of flight.
I will be working on some pilot aids to make flying easier.
Happy Spring!!!
The interior of the MD500 is basically complete. The flight model allows for loops and rolls. But I still need to work on the âweather-vaningâ routine as the helicopter tends to wander around the sky. Weather-vaning is what helps keep the helicopter pointed in the direction of flight.
For some reason, I have had a great deal of trouble making all the bits and pieces appear properly in 3js. The vertical divider was a problem in both eternal and internal view. For example, if you look all the way to the right in the interior view, you will see the rotor blades popping through. When I tried to texture the whole interior, the blades were visible all around. So I had to use geometries to create interior highlights, such as the gap between the doors and the fuselage.
Also, working on the flight model made me realize how insane it is to even contemplate flying a helicopter upside down. In addition to the massive stress it would impose, the aerodynamics are insane. An airplane can fly upside down because the wings can produce both downward and upward lift. However, a helicopter produces only downward lift. This means that when the helicopter is upside down, any lift produced by the rotor is only pushing you faster towards the ground. The best that you could do is to reduce throttle, which will reduce the lift produced. If the blades are flat, they could create a lot of drag which could help slow your descent. The bottom line is that it does not make sense to fly a helicopter inverted for any length of time.
I learned a lot from adding an interior to the MD500. The procedure is to start with an instrument panel with a texture that shows all of the instruments and their faces. The panel can include transparent areas for instruments with parts that sit behind the panel - like the attitude indicator. In your program, you can then add pointers to all of the gauges and animate them. For the attitude indicator, you can create a textured sphere which sits behind the panel.
I have created a subdirectory in my GitHub repo for panels. This contains sample panel textures. It also includes models of animated instruments, such as (1) an external compass; and (2) an attitude indicator that you can plug into your panel. It also includes textures, such as the texture for the attitude indicator and for compasses.
I will be adding an interior to the Pup. You can watch my progress by running the Pup program and pressing âVâ to enter cockpit view.
UPDATE (Mar 28)
The interior model for the Sopwith Pup is basically done. I added operating instruments and an animated pilot. On the machine gun, I added an animation of the cocking lever.
All these improvements have apparently caught the attention of the enemy since, if you watch, you will see a flight of aircraft in front. You may join them and try to determine their intentions.
We will see what develops.
April 7
I just realized that it is not fair for you to have to try to take on 1917-18 German triplanes in a 1917 Sopwith Pup. So I am upgrading your ride to a 1917-18 Sopwith Camel - an improved version of the Pup and well suited for dogfighting.
Here is the link to the Sopwith Camel demo so you can watch the airplane take shape, including the cockpit view.
April 12
The Sopwith Camel is basically done. I am adding the link to the initial post. I did not have to create the model from scratch since there are some pretty amazing models available online which were designed for the old MS flight simulator (FSX). In this case, I uploaded a couple of models to Blender and combined them to create both external and internal models. This involved simplifying the geometry (including eliminating things that are not visible) and by converting and reducing and reworking textures - which take up most of the space. So the external model is less that 1Mb and the internal model is around 2.5Mb.
I have added more details to the cockpit view of the Sopwith Camel - such as the spinning electric generator on the right strut.
I was a bit baffled by the procedure for cocking the guns, which is normally accomplished by pulling on the lever that rotates when the gun is fired. With the cowling, reaching those levers would have been impossible - which is why earlier versions of the camel did not have a full cowling. I finally realized that you cock the guns by pushing down on the two long levers that extend from the back of the guns into the cockpit.
I gave the pilot a proper RAF flying leather jacket along with fur-lined gloves for cold weather flying. (Sorry, no long streaming scarf yet). I added a more colorful paint scheme with a version of the âGrim Reaperâ used in WWI.
I tried using a rigged pilot, but found that I could not smoothly combine two sets of animations which involved the same parts The throttle set-up is a bit simplified. In earlier planes, the pilot would set the throttle at a specific RPM and adjust the mixture for that RPM. To slow down, the pilot would push a âblip switchâ that would stop the engine from running. However the Camel had several intermediate blip settings. So I left in a normal throttle.
I have also not added the handling characteristics that made the plane a âpilot-killerâ. In the Camel, the whole engine rotated with the prop which acted like a huge gyro. This meant that you could bank much faster in one direction. The gyroscopic effect also causes the airplane to pitch up or down when the pilot banked the airplane. I am assuming that your pilot persona has mastered these issues.
I have added several friendly AAA guns to the landscape which attempt to target the enemy bomber. (I will be reducing the fire rate which is much too fast for WWI. It will align more closely with the flak explosions.)
This is a crazy project! At first I was struggling a bit to control the plane, but after playing for a little while it started feeling natural. The planes look really realistic, especially the helicopter â the propeller behaviour is insanely cool and probably my favourite part.
The amount of updates and improvements youâve added over time is honestly impressive too, from the flight physics to the cockpit details, weather-vaning, combat systems, ocean rendering, and even the terrain generation.
I would like to see some npc enemy planes which we can destroy or they can attack us. This will be very intersting
.


