This chapter explains the basic idea of 3D graphics and the subroutines that realize it. In addition, in this chapter, we will mainly proceed with the discussion using a mathematical method called coordinate transformation. It may be difficult to understand as it uses a lot of slightly different techniques than usual, such as calculating determinants, but it is the basics of 3D graphics, so please read it many times to understand it.
Objects displayed in 3D graphics are generally defined by the following four things.
By combining these four elements, 3D graphics makes it possible to display images on a monitor. Therefore, in this chapter, we will explain each of the three, excluding viewing conversion, in order, and then add more detailed explanations.
< Figure 4-1 Coordinate system used by Sega Saturn>
< Figure 4-2 Screen coordinate system>
< Figure 4-3 Concept of projection>
Figure 4-4 Projection plane in SGL
< Figure 4-5 Viewing angle image model>
To change perspective projection settings on SGL, use the function “slPerspective”.
< Figure 4-6 Differences in images due to angle of view values>
The display level is set using the function “slZdspLevel”.
The display level is determined by the point of view and the dividing point of the projection plane from which the image is projected.
display level | |||
---|---|---|---|
1/2 | 1/4 | 1/8 | |
Substitution value | 1 | 2 | 3 |
Figure 4-7 Display level
List 4-1 sample_4_2: Changes in video due to perspective
/*------------------------------------------------ ----------------------*/ /* Perspective Control */ /*------------------------------------------------ ----------------------*/ #include "sgl.h" extern PDATA PD_CUBE; void ss_main(void){ static ANGLE ang[XYZ]; static ANGLE angper[XYZ]; static FIXED pos[XYZ]; static ANGLE tmp = DEGtoANG(90.0); static ANGLE adang = DEGtoANG(0.5); slInitSystem(TV_320x224,NULL,1); slPrint("Sample program 4.2" , slLocate(6,2)); ang[X] = DEGtoANG(30.0); ang[Y] = DEGtoANG(45.0); ang[Z] = DEGtoANG( 0.0); pos[X] = toFIXED(50.0); pos[Y] = toFIXED(40.0); pos[Z] = toFIXED(20.0); slPrint("Perspective : " , slLocate(4,5)); while(-1){ slPerspective(tmp); slPrintHex(slAng2Dec(tmp) , slLocate(18,5)); tmp +=adang; if (tmp> DEGtoANG(160.0)) adang = DEGtoANG(-0.5); if (tmp< DEGtoANG(20.0)) adang = DEGtoANG(0.5); slPushMatrix(); { FIXED dz; dz = slDivFX(slTan(tmp>> 1), toFIXED(170.0)); slTranslate(pos[X] , pos[Y] , pos[Z] + dz); slRotX(ang[X]); slRotY(ang[Y]); slRotZ(ang[Z]); slPutPolygon(&PD_CUBE); } slPopMatrix(); slSynch(); } }
Flow 4-1 sample_4_2: Flowchart of image changes by perspective
< Figure 4-8 Various conversion operations on objects>
Note) Angles and variables are shown in degrees and floating for convenience.
List 4-2 below is a program that uses the library function "slRotY" to rotate the square polygon drawn in List 2-1 in Chapter 2 on the Y axis (single-axis rotation). The rotation matrix is expressed as:
< Listing 4-2 sample_4_3_1: Square polygon single axis rotation routine>
/*------------------------------------------------ ----------------------*/ /* Rotation of 1 Polygon [Y axis] */ /*------------------------------------------------ ----------------------*/ #include "sgl.h" extern PDATA PD_PLANE1; void ss_main(void) { static ANGLE ang[XYZ]; static FIXED pos[XYZ]; slInitSystem(TV_320x224,NULL,1); slPrint("Sample program 4.3.1" , slLocate(9,2)); ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0); pos[X] = toFIXED( 0.0); pos[Y] = toFIXED( 0.0); pos[Z] = toFIXED(220.0); while(-1){ slPushMatrix(); { slTranslate(pos[X] , pos[Y] , pos[Z]); slRotX(ang[X]); slRotY(ang[Y]); slRotZ(ang[Z]); ang[Y] += DEGtoANG(5.0); slPutPolygon(&PD_PLANE1); } slPopMatrix(); slSynch(); } }
Flow 4-2 sample_4_3_1: Square polygon single axis rotation routine flowchart
List 4-3 sample_4_3_2: Square polygon 2-axis rotation routine
/*------------------------------------------------ ----------------------*/ /* Rotation of 1 Polygon [X & Y axis] */ /*------------------------------------------------ ----------------------*/ #include "sgl.h" extern PDATA PD_PLANE1; void ss_main(void) { static ANGLE ang[XYZ]; static FIXED pos[XYZ]; slInitSystem(TV_320x224,NULL,1); slPrint("Sample program 4.3.2" , slLocate(9,2)); ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0); pos[X] = toFIXED( 0.0); pos[Y] = toFIXED( 0.0); pos[Z] = toFIXED(220.0); while(-1){ slPushMatrix(); { slTranslate(pos[X] , pos[Y] , pos[Z]); slRotX(ang[X]); slRotY(ang[Y]); slRotZ(ang[Z]); ang[X] += DEGtoANG(4.0); ang[Y] += DEGtoANG(2.0); slPutPolygon(&PD_PLANE1); } slPopMatrix(); slSynch(); } }
Listing 4-4 below uses the library function “slTranslate” to achieve translation parallel to the X axis. The Sin value is used to control the movement parameters. Changes in the angle value tmp control changes in the X coordinate value.
Parallel translation using “slTranslate” is expressed by the following formula.
Listing 4-4 sample_4_3_3: Square polygon parallel movement routine
/*------------------------------------------------ ----------------------*/ /* Parallel Translation of 1 Polygon [X axis] */ /*------------------------------------------------ ----------------------*/ #include "sgl.h" #define POS_Z 50.0 extern PDATA PD_PLANE1; void ss_main(void) { static ANGLE ang[XYZ]; static FIXED pos[XYZ]; static ANGLE tmp = DEGtoANG(0.0); slInitSystem(TV_320x224,NULL,1); slPrint("Sample program 4.3.3" , slLocate(9,2)); ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0); pos[X] = toFIXED( 0.0); pos[Y] = toFIXED( 0.0); pos[Z] = toFIXED(220.0); while(-1){ slPushMatrix(); { slTranslate(pos[X] , pos[Y] , pos[Z]); slRotX(ang[X]); slRotY(ang[Y]); slRotZ(ang[Z]); tmp += DEGtoANG(5.0); pos[X] = slMulFX(toFIXED(POS_Z), slSin(tmp)); slPutPolygon(&PD_PLANE1); } slPopMatrix(); slSynch(); } }
<Flow 4-3 sample_4_3_3: Square polygon parallel movement flowchart>
Parameter range | |||||
---|---|---|---|---|---|
scale< 0.0 | scale=0.0 | 0.0< scale< 1.0 | scale=1.0 | 1.0< scale | |
Conversion result | mirror image | Disappearance | reduction | Same size | expansion |
Note) “Scale” refers to the scale parameter.
Listing 4-5 below is a program that accomplishes scaling. The scale ratio of the square polygon in the X-axis direction and Y-axis direction is changed.
Listing 4-5 sample_4_3_4: Square polygon scaling routine
/*------------------------------------------------ ----------------------*/ /* Expansion & Reduction of 1 Polygon [X & Y axis] */ /*------------------------------------------------ ----------------------*/ #include "sgl.h" extern PDATA PD_PLANE1; void ss_main(void) { static ANGLE ang[XYZ]; static FIXED pos[XYZ]; static FIXED sclx, scly, sclz, tmp = toFIXED(0.0); static Sint16 flag = 1; slInitSystem(TV_320x224,NULL,1); slPrint("Sample program 4.3.4" , slLocate(9,2)); ang[X] = ang[Y] = ang[Z] = DEGtoANG(0.0); pos[X] = toFIXED( 0.0); pos[Y] = toFIXED( 0.0); pos[Z] = toFIXED(220.0); sclx = scly = sclz = toFIXED(1.0); while(-1){ slPushMatrix(); { slTranslate(pos[X] , pos[Y] , pos[Z]); slRotX(ang[X]); slRotY(ang[Y]); slRotZ(ang[Z]); if (flag == 1) tmp += toFIXED(0.1); else tmp -= toFIXED(0.1); if (tmp > toFIXED( 1.0)) flag = 0; if (tmp < toFIXED(-1.0)) flag = 1; slScale(sclx + tmp, scly - tmp, sclz); slPutPolygon(&PD_PLANE1); } slPopMatrix(); slSynch(); } }
<Flow 4-4 sample_4_3_4: Square polygon scaling flowchart>
Substitute the sine and cosine values and add rotation around the X axis.
Assign the Sin and Cos values to the parameters as FIXED type numbers.
Substitute the sine and cosine values and add rotation around the Y axis
Assign the Sin and Cos values to the parameters as FIXED type numbers.
Substitute the sine and cosine values and add rotation around the Z axis.
Assign the Sin and Cos values to the parameters as FIXED type numbers.
Adds rotation around an arbitrary axis passing through the origin (axis units are specified as vector values).
Assign the unit vector value (XYZ) representing the rotation axis and rotation angle value to the parameters.
Always substitute a value that is a unit vector for the vector value representing the rotation axis.
A unit vector is a vector whose magnitude is always 1.
< Figure 4-9 Differences in results depending on conversion order>
Note) Angles and variables are shown in degrees and floating for convenience.
< Figure 4-10 Example of 2D clipping>
Note) When the display area is a projection plane closed by clipping boundaries
As shown in the image above, objects targeted for clipping can be shown or hidden inside and outside the clipping area. In this example, if one object covers both sides of the clipping area, part of the object (inside the area) will be visible, and part (outside the area) will not be displayed.
Note
In some cases, due to problems with calculation speed and drawing speed, display or non-display may be switched depending on the percentage of one object included in the clipping area.
left side of visual field | : Clipping plane (determined by angle of view value) |
right side of field of vision | : Clipping plane (determined by angle of view value) |
top of field of view | : Clipping plane (determined by angle of view value and screen mode) |
lower surface of the field of vision | : Clipping plane (determined by angle of view value and screen mode) |
front of field of view | : Front limit surface (determined by function “slZdspLevel”) |
posterior aspect of visual field | : Backward limit surface (determined by parameter “Zlimit” in function “slWindow”) |
Figure 4-11 Defining the display area by 3D clipping
Figure 4-12 Example of 3D clipping
< Figure 4-13 Window concept>
Figure 4-14 Meaning of parameters in “slWindow”
Note) left, top, right, bottom, CENTER_X, CENTER_Y indicate the XY coordinate values for the monitor.
Figure 4-15 Difference in images due to CENTER_X and CENTER_Y
Note) Conditions such as object and viewpoint are the same for both a) and b)
●For screen mode (320 horizontal x 240 vertical)slWindow(0,0,319,223,0x7FFF,160,112); | | | | | Vanishing point coordinates: center of screen | Zlimit Window range indication coordinate value
Figure 4-17 Example of object display using a window
Note 1) Object 1 is displayed outside the window
Note 2) Object 2 is displayed in the window
/* Foreword omitted */ ATTR attribute_PLANE[] = { ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(16,16,16), No_Gouraud, MESHoff|Window_Out, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(00,31,31), No_Gouraud, MESHoff|Window_Out, sprPolygon,No_Option), }; ATTR attribute_CUBE[] = { ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,31,31), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,00,00), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(00,31,00), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(00,00,31), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(31,31,00), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), ATTRIBUTE(Single_Plane, SORT_MIN, No_Texture, C_RGB(00,31,31), No_Gouraud, MESHoff|Window_In, sprPolygon,No_Option), }; /* omitted */
Only one window setting is active at a time. Also, when you call the function "slWindow", the priority is separated from the polygons (sprites) before it and those after it, and in this case, the latter always takes precedence.
: /* Window 1 (default) */ slPutPolygon( object1 ); : slPutPolygon( object2 ); : slWindow(.....); ← : /* Wind 2 */ slPutPolygon( object3 ); : slWindow(.....); ←Error: /* Stay in window 2 */ slPutPolygon( object4 ); : slPutPolygon( object5 ); :
functional type | function name | parameters | function |
---|---|---|---|
void | slPerspective | ANGLE angp | Perspective conversion table settings |
void | slRotX | ANGLE angx | Rotation of polygon data around the X axis |
void | slRotY | ANGLE | Rotation of polygon data around the Y axis |
void | slRotZ | ANGLE angz | Rotation of polygon data around the Z axis |
void | slRotXSC | FIXED sn,FIXED cs | Rotation around the X axis by specifying Sin and Cos |
void | slRotYSC | FIXED sn,FIXED cs | Rotation around the Y axis by specifying Sin and Cos |
void | slRotZSC | FIXED sn,FIXED cs | Rotation around the Z axis by specifying Sin and Cos |
void | slRotAX | FIXED vx,vy,cz,ANGLE a | Rotation around any axis passing through the origin (axis unit: vector) |
void | slScale | FIXED sx,sy,sz | Scaling polygon data |
void | slWindow | lft,top,rgt,btm,Zlimit,CNTX,CNTY | Window settings |
void | slZdspLevel | level | Viewing volume display level specification |