1 /*---------------------------------------------------------------------------*
2 Project: KPAD sample program
3 File: graphic.c
4 Programmer: Keizo Ohta
5
6 Copyright 2005 Nintendo. All rights reserved.
7
8 These coded instructions, statements, and computer programs contain
9 proprietary information of Nintendo of America Inc. and/or Nintendo
10 Company Ltd., and are protected by Federal copyright law. They may
11 not be disclosed to third parties or copied or duplicated in any form,
12 in whole or in part, without the prior written consent of Nintendo.
13 *---------------------------------------------------------------------------*/
14
15 #include <revolution.h>
16 #include <math.h>
17
18 #include "graphic.h"
19
20
21 /***************************************************************
22 Variables
23 ***************************************************************/
24 GXColor black_clr = { 0, 0, 0, 255 } ;
25 GXColor smoke_clr = { 61, 61, 61, 255 } ;
26 GXColor gray_clr = { 129,129,129, 255 } ;
27 GXColor white_clr = { 255,255,255, 255 } ;
28 GXColor silver_clr = { 193,193,193, 255 } ;
29 GXColor red_clr = { 237, 28, 36, 255 } ;
30 GXColor green_clr = { 0,166, 81, 255 } ;
31 GXColor blue_clr = { 0, 84,166, 255 } ;
32 GXColor yellow_clr = { 255,242, 0, 255 } ;
33 GXColor cyan_clr = { 0,174,239, 255 } ;
34 GXColor magenta_clr = { 236, 0,140, 255 } ;
35 GXColor orange_clr = { 245,125, 32, 255 } ;
36 GXColor violet_clr = { 102, 45,145, 255 } ;
37 GXColor peagreen_clr = { 141,198, 63, 255 } ;
38
39
40 /*******************************************************************************
41 Initialize drawing of simple graphics
42 fb_width : Horizontal resolution of frame buffer
43 fb_height : Vertical resolution of frame buffer
44 *******************************************************************************/
init_draw_graphic(u16 fb_width,u16 fb_height)45 void init_draw_graphic( u16 fb_width, u16 fb_height )
46 {
47 Mtx44 proj_mtx ;
48 Mtx view_mtx ;
49 f32 canvas_wd, canvas_ht ;
50
51
52 //Code for working around XF stall bug
53 GXSetMisc( GX_MT_XF_FLUSH, GX_XF_FLUSH_SAFE ) ;
54
55 //----- Virtual canvas size
56 canvas_wd = fb_width * 0.91346f ;
57 canvas_ht = fb_height ;
58
59 //----- MTX
60 MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ;
61 GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ;
62
63 MTXIdentity( view_mtx ) ;
64 GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ;
65 GXSetCurrentMtx( GX_PNMTX0 ) ;
66
67 //----- VERTEX
68 GXClearVtxDesc() ;
69 GXSetVtxDesc( GX_VA_POS, GX_DIRECT ) ;
70 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0 ) ;
71
72 //----- CHANNEL
73 GXSetNumChans( 1 ) ;
74 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
75 GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
76
77 //----- TEXTURE
78 GXSetNumTexGens( 0 ) ;
79
80 //----- TEV
81 GXSetNumTevStages( 1 ) ;
82 GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL ) ;
83 GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0 ) ;
84 GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
85 GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0 ) ;
86 GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
87 GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ;
88
89 //----- SCREEN
90 GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ;
91 GXSetAlphaUpdate( GX_DISABLE ) ;
92
93 GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ;
94 GXSetCullMode( GX_CULL_BACK ) ;
95 }
96
97
98 /*******************************************************************************
99 Draw point
100 *******************************************************************************/
draw_point(f32 px,f32 py,GXColor clr,f32 size)101 void draw_point( f32 px, f32 py, GXColor clr, f32 size )
102 {
103 GXSetTevColor( GX_TEVREG0, clr ) ;
104 GXSetPointSize( (u8)(s32)(size * 6.0f + 0.5f), GX_TO_ZERO ) ;
105
106 GXBegin( GX_POINTS, GX_VTXFMT0, 1 ) ;
107 GXPosition2f32( px, py ) ;
108 GXEnd() ;
109 }
110
111
112 /*******************************************************************************
113 Draw line
114 *******************************************************************************/
draw_line(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)115 void draw_line( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
116 {
117 GXSetTevColor( GX_TEVREG0, clr ) ;
118 GXSetLineWidth( (u8)(s32)(width * 6.0f + 0.5f), GX_TO_ZERO ) ;
119
120 GXBegin( GX_LINES, GX_VTXFMT0, 2 ) ;
121 GXPosition2f32( x1, y1 ) ;
122 GXPosition2f32( x2, y2 ) ;
123 GXEnd() ;
124 }
125
126
127 /*******************************************************************************
128 Draw broken line
129 *******************************************************************************/
draw_dashed_line(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)130 void draw_dashed_line( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
131 {
132 const int DIV=5;
133 int i=0;
134 f32 dx = x2 - x1;
135 f32 dy = y2 - y1;
136 f32 length = (f32)sqrt(dx*dx + dy*dy);
137 GXSetTevColor( GX_TEVREG0, clr ) ;
138 GXSetLineWidth( (u8)(s32)(width * 6.0f + 0.5f), GX_TO_ZERO ) ;
139
140 for(i=0; i<DIV; ++i){
141 GXBegin( GX_LINES, GX_VTXFMT0, 2 ) ;
142 GXPosition2f32( x1+dx/(2*DIV)*(2*i+0), y1+dy/(2*DIV)*(2*i+0) ) ;
143 GXPosition2f32( x1+dx/(2*DIV)*(2*i+1), y1+dy/(2*DIV)*(2*i+1) ) ;
144 GXEnd() ;
145 }
146 }
147
148
149 /*******************************************************************************
150 Draw arrow
151 *******************************************************************************/
draw_arrow(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)152 void draw_arrow( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
153 {
154 f32 vx,vy, f ;
155
156
157 vx = x2 - x1 ;
158 vy = y2 - y1 ;
159 f = sqrtf( vx*vx + vy*vy ) ;
160 if ( f == 0.0f ) {
161 vx = vy = 0.0f ;
162 } else {
163 f = width * 2.0f / f ;
164 vx *= f ;
165 vy *= f ;
166 }
167 draw_line( x1,y1, x2,y2, clr, width ) ;
168 draw_line( x2,y2, x2-vx-vx-vy,y2-vy-vy+vx, clr, width ) ;
169 draw_line( x2,y2, x2-vx-vx+vy,y2-vy-vy-vx, clr, width ) ;
170 }
171
172
173 /*******************************************************************************
174 Draw arrow (broken line)
175 *******************************************************************************/
draw_dashed_arrow(f32 x1,f32 y1,f32 x2,f32 y2,GXColor clr,f32 width)176 void draw_dashed_arrow( f32 x1, f32 y1, f32 x2, f32 y2, GXColor clr, f32 width )
177 {
178 f32 vx,vy, f ;
179
180
181 vx = x2 - x1 ;
182 vy = y2 - y1 ;
183 f = sqrtf( vx*vx + vy*vy ) ;
184 if ( f == 0.0f ) {
185 vx = vy = 0.0f ;
186 } else {
187 f = width * 2.0f / f ;
188 vx *= f ;
189 vy *= f ;
190 }
191 draw_dashed_line( x1,y1, x2,y2, clr, width ) ;
192 draw_line( x2,y2, x2-vx-vx-vy,y2-vy-vy+vx, clr, width ) ;
193 draw_line( x2,y2, x2-vx-vx+vy,y2-vy-vy-vx, clr, width ) ;
194 }
195
196
197 /*******************************************************************************
198 Draw circle
199 *******************************************************************************/
draw_circle(f32 ox,f32 oy,f32 radius,GXColor clr,f32 width)200 void draw_circle( f32 ox, f32 oy, f32 radius, GXColor clr, f32 width )
201 {
202 s32 vtxs = 40 ; // Number of vertices
203 f32 k = 6.29f / (f32)vtxs ; // 2pi divided by the number of sections
204 s32 n ;
205 f32 f, vx,vy ;
206
207
208 if ( radius < width * 0.1f ) {
209 //----- Radii that are too small are handled as points
210 draw_point( ox,oy, clr, width ) ;
211 return ;
212 }
213
214 GXSetTevColor( GX_TEVREG0, clr ) ;
215 GXSetLineWidth( (u8)(s32)(width * 6.0f + 0.5f), GX_TO_ZERO ) ;
216
217 GXBegin( GX_LINESTRIP, GX_VTXFMT0, (u16)(vtxs + 1) ) ;
218
219 vx = radius ;
220 vy = 0.0f ;
221 n = vtxs ;
222 do {
223 GXPosition2f32( ox + vx, oy + vy ) ;
224
225 //----- Proceed in the direction of angular velocity
226 f = vx ;
227 vx -= vy * k ;
228 vy += f * k ;
229
230 //----- Correct radius
231 f = radius / sqrtf( vx * vx + vy * vy ) ;
232 vx *= f ;
233 vy *= f ;
234 } while ( --n != 0 ) ;
235
236 GXPosition2f32( ox + radius, oy ) ; // The last point is the same as the start point
237 GXEnd() ;
238 }
239
240