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