New ways to have fun with CFS1

Thanks again Hubba for all of this time consuming work and the way that you put it together so that even lame ducks like myself can at least keep up.

Dave www.thefreeflightsite.com

I can't tell your "degree of computer proficiency" just looking at your posts, but you have a PC and you know how to type on the keyboard. This fulfill the "average Joe" I'm targeting...:kilroy: The rest is simply "getting the hang of it".
 
Lesson #2: automatic calculation (part one)

Re-reading myself in our first lesson, I think I made a very poor job of explaining vectors. Maybe this site will do it better. I also hope this drawing will help;

View attachment 36605

The formula of the preceding lesson was just an application of the Pythagorean Theorem to 3D distance. The vector length is determined by the distance between RefPoint and the surface on which our polygon stands. The vector coordinates are as long as possible to increase accuracy, the same way an architect protractor is way larger than a first grade schoolboy protractor. The vector length is capable of a precision of six digits after the decimal point, again for accuracy purpose. Back to lesson 2.

By one of these mysteries fathered by the twisted minds of programmers, automation is for humans and "manual" for computers... go figure!

Now that we have saved our souls from eternal mathematical damnation, a word about our savior; the automatic calculation.

How does automatic calculation works? We need to know that, if only to use it wisely.

The "a" is for "automatic" and "ai" for "automatic inverted". Basically, automatic calculation will texture the side exterior to RefPoint and automatic inverted the side interior to RefPoint if your polygon's vertices are called in a clockwise order. This is, almost verbatim, the usual formula "experts" are using. I must say, to my own shame, that I never explored thoroughly the automatic calculation. When things were not going my way, I would fiddle around until they did. So this lesson will be as much for me as it is for you; let's learn together, shall we?

We need to turn our "wall" into a "yard" first. This drawing should help you to follow;

View attachment 36606

We will "paint" each interior walls first, then exterior ones. From the exterior, points calling is done clockwise and, when seen from the interior, anticlockwise. Refer to the drawing above;

:BEGINNING
;Yard red and green 10x10x10
Points( 1 ; 8 points
780 0 780 ; 1
780 1560 780 ; 2
780 1560 -780 ; 3
780 0 -780 ; 4
-780 0 780 ; 5
-780 1560 780 ; 6
-780 1560 -780 ; 7
-780 0 -780 ; 8
)
SurfaceColor( 05 F0 ) ;red
Poly( ai 1 2 6 5 ) ;fore int
Poly( ai 8 7 3 4 ) ;aft int
Poly( ai 4 3 2 1 ) ;right int
Poly( ai 5 6 7 8 ) ;left int
SurfaceColor( 06 F0 ) ;green
Poly( a 1 2 6 5 ) ;fore ext
Poly( a 8 7 3 4 ) ;aft ext
Poly( a 4 3 2 1 ) ;right ext
Poly( a 5 6 7 8 ) ;left ext
Return

Interior walls are painted (spoiler alert!!!) red (05) and exterior walls green (06). At least, that is what I'm trying to do. So, is it?

View attachment 36607

Yippee! It works! You will note that, by painting the interior walls first, we have eluded bleeds.

Now, we will invert the points' calling order so that they will be called anticlockwise from the exterior and clockwise from the inside. This is to test the "clockwise-anticlockwise" theory which, if right, should gives us green interior and red exterior.

:BEGINNING
;Yard red and green 10x10x10
Points( 1 ; 8 points
780 0 780 ; 1
780 1560 780 ; 2
780 1560 -780 ; 3
780 0 -780 ; 4
-780 0 780 ; 5
-780 1560 780 ; 6
-780 1560 -780 ; 7
-780 0 -780 ; 8
)
SurfaceColor( 05 F0 ) ;red
Poly( ai 5 6 2 1 ) ;fore int
Poly( ai 4 3 7 8 ) ;aft int
Poly( ai 1 2 3 4 ) ;right int
Poly( ai 8 7 6 5 ) ;left int
SurfaceColor( 06 F0 ) ;green
Poly( a 5 6 2 1 ) ;fore ext
Poly( a 4 3 7 8 ) ;aft ext
Poly( a 1 2 3 4 ) ;right ext
Poly( a 8 7 6 5 ) ;left ext
Return


Naaaa... walls remained red inside and green outside. SCASM does recognize if a polygon's surface is away from RefPoint (exterior) or facing it (interior) during compilation, no matter if points are called clockwise or anticlockwise. To verify what happened, I have saved the visual code as found in playground.scx. The first assembly is in blue, the second in red.

:L001284
Points( 1 ; 8 points
780 0 780 ; 1
780 1560 780 ; 2
780 1560 -780 ; 3
780 0 -780 ; 4
-780 0 780 ; 5
-780 1560 780 ; 6
-780 1560 -780 ; 7
-780 0 -780 ; 8
)
SurfaceColor( 0x05 0xF0 )
Poly( m 0 0 -32767 -780.000000 1 2 6 5 )
Poly( m 0 0 32767 -780.000000 8 7 3 4 )
Poly( m -32767 0 0 -780.000000 4 3 2 1 )
Poly( m 32767 0 0 -780.000000 5 6 7 8 )
SurfaceColor( 0x06 0xF0 )
Poly( m 0 0 32767 780.000000 1 2 6 5 )
Poly( m 0 0 -32767 780.000000 8 7 3 4 )
Poly( m 32767 0 0 780.000000 4 3 2 1 )
Poly( m -32767 0 0 780.000000 5 6 7 8 )
Return


:L001284
Points( 1 ; 8 points
780 0 780 ; 1
780 1560 780 ; 2
780 1560 -780 ; 3
780 0 -780 ; 4
-780 0 780 ; 5
-780 1560 780 ; 6
-780 1560 -780 ; 7
-780 0 -780 ; 8
)
SurfaceColor( 0x05 0xF0 )
Poly( m 0 0 -32767 -780.000000 5 6 2 1 )
Poly( m 0 0 32767 -780.000000 4 3 7 8 )
Poly( m -32767 0 0 -780.000000 1 2 3 4 )
Poly( m 32767 0 0 -780.000000 8 7 6 5 )
SurfaceColor( 0x06 0xF0 )
Poly( m 0 0 32767 780.000000 5 6 2 1 )
Poly( m 0 0 -32767 780.000000 4 3 7 8 )
Poly( m 32767 0 0 780.000000 1 2 3 4 )
Poly( m -32767 0 0 780.000000 8 7 6 5 )
Return


The "manual" vectoring is exactly the same between both assemblies; vx, vz, vy, and vector length are unchanged. As long as points are being called in a sequence respecting the perimeter, SCASM will properly identify exterior-interior orientation. By "respecting the perimeter", I mean clockwise or anticlockwise. For example, the fore wall sequence "5 2 6 1" would compile but create a "bow-tie" weird look. Go and try it if you want.

These SCASM SCX are also good examples of what I've tried explaining in the preceding lesson. As all walls are perpendicular to Y or X axis, you see ±32767 as vx or vy. Vector length is always at 780.000000 (the minus sign is only there to indicate direction). For example, in the last assembly, the interior fore wall is at vy = -32767 and vector length at -780.000000 because the vector is "read" from tip to tail. The same fore wall, but from the exterior, has vy = 32767 and vector length at 780.000000 simply because now it is "read" from tail to tip. In both cases, vector has the same length. Study these two SCX carefully until our next lesson.

Next time; Lesson #3: automatic calculation (part two)
 
Lesson #3: automatic calculation (part two)

In the preceding lesson, we have establish that SCASM can "recognize" interior and exterior polygon's surfaces to RefPoint. But what about surfaces that have RefPoint as one of their vertices? What is "interior" and what is "exterior" when our polygons are "splitting" RefPoint?

For this lesson, we will return to our green-red wall;

:BEGINNING
;Wall red and green 10x10
Points( 1 ; 4 points
0 0 780 ; 1
0 1560 780 ; 2
0 1560 -780 ; 3
0 0 -780 ; 4
)
SurfaceColor( 05 F0 )
Poly( ai 1 2 3 4 )
SurfaceColor( 06 F0 )
Poly( a 1 2 3 4 )
Return


Logically, red is "interior" and green is "exterior", so right is "interior" and left is "exterior". But what happens when we change the calling order of the points from "1 2 3 4" to "4 3 2 1"? Go and try it.

View attachment 36778 Oops! Colors have switched! So now, "interior" is left and "exterior" is right. We will now try with a fore-aft wall splitting RefPoint;

:BEGINNING
;Wall red and green 10x10
Points( 1 ; 4 points
780 0 0 ; 1
780 1560 0 ; 2
-780 1560 0 ; 3
-780 0 0 ; 4
)
SurfaceColor( 05 F0 )
Poly( ai 1 2 3 4 ) ;or 4 3 2 1

SurfaceColor( 06 F0 )
Poly( a 1 2 3 4 ) ;or 4 3 2 1
Return


View attachment 36779

Again, colors, therefore sides, are switching depending on the order of our points (vertices) calling. We can repeat the experiment on a "floor" at Refpoint level;

:BEGINNING
;Wall red and green 10x10
Points( 1 ; 4 points
780 0 780 ; 1
780 0 -780 ; 2
-780 0 -780 ; 3
-780 0 780 ; 4
)
SurfaceColor( 05 F0 )
Poly( ai 1 2 3 4 ) ;or 4 3 2 1
SurfaceColor( 06 F0 )
Poly( a 1 2 3 4 ) ;or 4 3 2 1
Return


View attachment 36780 I only have taken screen captures of the top side, but you can take my word that the bottom follows the same pattern (or you can go and try it yourself!).

The top of our floor changes color depending on the order we called our points. Now, have a look at the three preceding pictures and tell me when green (exterior) is on the left, fore, or top side.

When it is on "clockwise" order! And when going counterclockwise, green (exterior) is on the right - aft - bottom side. As a convention, left, top, and front sides are usually the ones we're referring to;

View attachment 36781 this is how AF99 is rigged, and this is how airplanes are flying (unless you want to fly tail first...).

View attachment 36782 Unless I specifically say otherwise, these perspectives are to be used from now on.

So, to resume, using "a" (automatic) or "ai" (automatic inverted) attributes, we can choose which side (interior or exterior) we want to paint. One exception is when RefPoint is a vertex among others vertices of our polygon's plane surface. In this particular case, exterior is clockwise and interior is counterclockwise.

In lesson #4, we will look at scales and the command SetScalex.
 
Lesson #4: scales

SCASM unit is "dimensionless", but it gets a dimension with a scaling command. Scenery designers used to make their macros (subroutines for buildings and stuff integrated in a BGL scenery file) using the SetScale or ReScale commands. This had the advantage of permitting decimal with floating point value. But it was "computer unfriendly" and forced the Flight Simulator EXE (COMBATFS.EXE for CFS1) to go through long calculations, slowing down framerate eventually. SetScaleX, originally created for aircraft (moving objects) was adopted by scenery-builders as well. This is probably due to its more "computer friendly" approach by "bit shifting".

Incidentally; why 156 units equal one feet at SetScalex 7?

According to Manfred Moldenhauer, when the scale is 1:1, each unit represent 1 meter. The following insert is a table for SetScaleX I have done a while ago (copy and paste if you want);
----------------
scaling with SetScalex instruction

Mathematical formulas:
scale = ( 2^SX ) / 65536
scale = 1 / 2^(16-SX)
or or 1 meter= ? units
5- 0.00048828125 1/2048 2048
6- 0.0009765625 1/1024 1024
7- 0.001953125 1/512 512
8- 0.00390625 1/256 256
9- 0.078125 1/128 128
10- 0.015625 1/64 64
11- 0.03125 1/32 32
12- 0.0625 1/16 16
13- 0.125 1/8 8
14- 0.25 1/4 4
15- 0.5 1/2 2
16- 1 1 1
17- 2 2 0.5
18- 4 4 0.25

From SetScalex 7 to;
5- x 0.25
6- x 0.5
8- x 2
9- x 4
10- x 8
11- x 16
12- x 32
13- x 64
14- x 128
15- x 256
16- x 512
17- x 1024
18- x 2048
----------------

Since 1 foot = .3048 meter and that, at SetScaleX 7, a meter = 512 units, it should be .3048 x 512 = 156.0576. AF99 rounds-up at 156.13. We will round-down at 156, which is even more precise than AF99.

As you can see, progression is done by multiple of two (2^SX), the same "language" PC (or Mac and Linux for that matter) is familiar with. The advantage is a gain in speed calculation, the disadvantage is a certain rigidity in scaling. For example, you can double the size of an object, but not triple it. Some forethought is in order.

Scale is to be determined on basically two opposing considerations: 1) How detailed do I want my object to be? ; 2) How big do I want my object to be? If I want to make a very detailed object, for example a violin, scales under 7 are to be considered. If I want to make a very large building, or a mountain, scales over 7 come to mind. But for now, we will use 7 as a good compromise.

Incidentally, if you were curious enough, you may have seen that CFS1 stock, flyable and non-flyable, aircraft are at 180. According to Manfred Moldenhauer, any values above 31 "are interpreted as a local variable which carry the scaling information in the normal fractional format". Said differently, that CFS1 value of 180 refers not to a SetScaleX value, but to a SetScale "sorta" command somewhere in the non-BGL part of the MDL. FS98 stock aircraft are all using a SetscaleX of 6, which is a "real" scale.

Taken from the same distance under the same angle, here is "our" wall at different scales;

View attachment 36946

12 was the maximum possible under the circumstances, anything bigger simply wouldn't fit CFS1 window!

In the next lesson (#5), we will start to study color commands. Can't say how many lessons it will take, but certainly more than one.
 
Lesson #5: colors (part one)

To begin, we will build a cube. This cube will play an important role for many lessons to come. I am reproducing here a drawing that was used in lesson #2 to build the "yard". It uses the same eight points' declaration. We will simply add a top and a bottom to the ensemble.

attachment.php


:BEGINNING
Call( :TheCube )
Return

:TheCube ;10x10x10 cube
Points( 1 ; 8 points
780 0 780 ; 1
780 1560 780 ; 2
780 1560 -780 ; 3
780 0 -780 ; 4
-780 0 780 ; 5
-780 1560 780 ; 6
-780 1560 -780 ; 7
-780 0 -780 ; 8
)
SurfaceColor( 05 F0 ) ;red
Poly( ai 5 8 4 1 ) ;bottom int
Poly( ai 2 3 7 6 ) ;top int
Poly( ai 1 2 6 5 ) ;fore int
Poly( ai 8 7 3 4 ) ;aft int
Poly( ai 4 3 2 1 ) ;right int
Poly( ai 5 6 7 8 ) ;left int
SurfaceColor( 06 F0 ) ;green
Poly( a 5 8 4 1 ) ;bottom ext
Poly( a 2 3 7 6 ) ;top ext
Poly( a 1 2 6 5 ) ;fore ext
Poly( a 8 7 3 4 ) ;aft ext
Poly( a 4 3 2 1 ) ;right ext
Poly( a 5 6 7 8 ) ;left ext
Return

You will note that two subroutines have been created (:BEGINNING and :TheCube). The first subroutine simply call the second one, why? Because, this way, ":BEGINNING" will always be the first subroutine called, no matter what other subroutines it will call in return. When we'll add other subroutines,and we certainly will, they'll always be tied-up in some ways to ":BEGINNING" without having to change that Label called in the opening lines three times. This, in turn, increases the reading delay, but so lightly that it doesn't really matter. The advantages outweigh the inconveniences by a fairly large margin as the Call command is one of the fastest read, if not the fastest.

The second subroutine is basically what ":BEGINNING" used to be. The description line is behind semi-colon after the Label ":TheCube", which is pretty much self-describing. All the six surfaces are painted first from the interior, then from the exterior. Note that the bottom points' calling is done counterclockwise so that red will be in the interior. The other surfaces will automatically choose the "right" side to be painted.

Once compiled, you should see an interior with some different shades of red (S key once), this is called "hard shading" and will do the job for rectangular or "un-round" shapes. But the exterior view is much more interesting to look at;

View attachment 38127 the green also appear in different shades. If you let time go by (hint; use CFOWeather "Time and Season") you'll see this;

View attachment 38128

This is a view from 6 AM to 6 PM from 10h30 O'clock high. At night, the cube, internally and externally, will be pitch black;

View attachment 38129

These are "old" colors dating back to FS5 but still in use in AF99. The command line goes this way;

SurfaceColor( num attr )

Where num is the hexadecimal color code (you will often see 0x, a prefix announcing an hex number, in SCASM SCX) and attr the color attribute, also hexadecimal. The attribute F0, most frequently used, is for normal colors changing with sun ray's direction. In the next lesson (#6), we will study them.
 
Lesson #6: colors (part two)

The following list does enumerate the documented solid colors. A more extensive list will come later;
----------------
Colour Name / 16bit Value
C_BLACK / 00
C_DKGRAY / 01
C_GRAY / 02
C_LTGRAY / 03
C_WHITE / 04
C_RED
/ 05
C_GREEN
/ 06
C_BLUE
/ 07
C_ORANGE
/ 08
C_YELLOW
/ 09
C_BROWN
/ 0A
C_TAN
/ 0B
C_BRICK
/ 0C
C_OLIVE
/ 0D
C_WATER
/ 0E

View attachment 38134 All these colors are shaded during daylight and pitch black at night.

C_BRIGHT_RED / 0F
C_BRIGHT_GREEN
/ 10
C_BRIGHT_BLUE
/ 11
C_BRIGHT_AQUA
/ 12
C_BRIGHT_ORANGE
/ 13
C_BRIGHT_YELLOW
/ 14
C_BRIGHT_WHITE
/ 15
C_CONST_WHITE
/ 16

View attachment 38135 All these colors are unshaded during daylight and keep their colors at night. Can't say for sure if there's a difference between 15 and 16, maybe the latter is a tid bit brighter, maybe.

C_DARK_RED / 17
C_DARK_GREEN
/ 18
C_DARK_BLUE
/ 19
C_DARK_ORANGE
/ 1A
C_DARK_YELLOW
/ 1B
C_DARK_BROWN
/ 1C
C_DARK_TAN
/ 1D
C_DARK_BRICK
/ 1E
C_DARK_OLIVE
/ 1F

View attachment 38136 Darker shaded colors during daylight but pitch black at night. Similar to 00 - 0E in properties.

C_MED_RED / 20
C_MED_GREEN
/ 21
C_MED_BLUE
/ 22
C_MED_ORANGE
/ 23
C_MED_YELLOW
/ 24
C_MED_BROWN
/ 25
C_MED_TAN
/ 26
C_MED_BRICK
/ 27
C_MED_OLIVE
/ 28

View attachment 38137 Medium-dark shaded colors during daylight but pitch black at night. Similar to 00 - 0E in properties.

C_LIGHT_RED / 29
C_LIGHT_GREEN
/ 2A
C_LIGHT_BLUE
/ 2B
C_LIGHT_ORANGE
/ 2C
C_LIGHT_YELLOW
/ 2D
C_LIGHT_BROWN
/ 2E
C_LIGHT_TAN
/ 2F
C_LIGHT_BRICK
/ 30
C_LIGHT_OLIVE
/ 31

View attachment 38138 Lighter dark shaded colors during daylight but pitch black at night. Similar to 00 - 0E in properties.

C_BRIGHT_DKGRAY / 32
C_BRIGHT_GRAY
/ 33
C_BRIGHT_LTGRAY
/ 34

View attachment 38139 Unshaded gray tones during daylight visible at night. Similar to 0F - 16 in properties.

----------------

These are "officials" F0 attribute colors. The palette is limited but sufficient for basic objects. Anyway, this is what AF99 has to offer in terms of solid colors. Curiosity had me look beyond those documented colors, which will be the subject of our next lesson (#7).
 
Lesson #7: colors (part three)

Normally, I would have stopped at color 34 and went for transparent attribute. But, as I was working on these transparent colors, I found that hexadecimal palette was going further. So, out of curiosity, I went back to solid colors beyond 34. This is what I've found;

f0demicolors.jpg


These colors are not disorganized, which proves that they are not placed aleatory. This palette is filled with pitch black entries, all removed here, that tend to make you think they are. Some are simply doubles of previous colors, but many do offer different nuances, and some are night colors. I stopped at 116 because it was starting to get redundant, but you may explore even further. We will now explore the transparent colors attribute.

Attribute 68 is for transparency and should, in theory, work with all the preceding colors. The way it works need to be explored a bit: this will be our next (#8) lesson.
 
OOOPS!

As I was preparing the next lessons, I realized that I was committing an "hexadecimal sin"! Next number after 9F is not 100, which is 256 in decimal, but A0! Here is the "missing" rest of the palette;

f0colorssuitedemi.jpg


The series between 9F and AF is of particular interest; it gives a pitch black in daylight that turns into a shade of orange at night. Back to regular schedule...
 
OOOPS! (revisited)

"There are more things in heaven and earth, Horatio,..." Sorry for my poor man's Shakespeare quote (I'm more a Cyrano de Bergerac kind of guy myself), but basic palette still had surprises for me. My testing of the palette was done by looking at the cube in daylight then, after a screen capture, at night "just in case". This had me missing an important change happening between dusk/dawn with colors between EF and FF. Here is F3 from 4 AM to daylight;

View attachment 49409

As you can see it goes through gray, then red, then green and, finally, blue tones. Each "colors" has its own sequence, and F3 is not the wildest one! Here is FF in all its weirdness;

View attachment 49410

I don't have many uses in mind right now, but we never know!
 
Very interesting thread Hubba....I have many ideas I would like to try and implement into cfs1....not enough time in a day...Thanks for making this information available,I'm sure I will be referring to this information quite a lot.....:salute:
 
Back
Top