1 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2 /* If you are missing that file, acquire a complete release at teeworlds.com. */
5 #include <engine/graphics.h>
9 void CRenderTools::RenderEvalEnvelope(CEnvPoint
*pPoints
, int NumPoints
, int Channels
, float Time
, float *pResult
)
22 pResult
[0] = fx2f(pPoints
[0].m_aValues
[0]);
23 pResult
[1] = fx2f(pPoints
[0].m_aValues
[1]);
24 pResult
[2] = fx2f(pPoints
[0].m_aValues
[2]);
25 pResult
[3] = fx2f(pPoints
[0].m_aValues
[3]);
29 Time
= fmod(Time
, pPoints
[NumPoints
-1].m_Time
/1000.0f
)*1000.0f
;
30 for(int i
= 0; i
< NumPoints
-1; i
++)
32 if(Time
>= pPoints
[i
].m_Time
&& Time
<= pPoints
[i
+1].m_Time
)
34 float Delta
= pPoints
[i
+1].m_Time
-pPoints
[i
].m_Time
;
35 float a
= (Time
-pPoints
[i
].m_Time
)/Delta
;
38 if(pPoints
[i
].m_Curvetype
== CURVETYPE_SMOOTH
)
39 a
= -2*a
*a
*a
+ 3*a
*a
; // second hermite basis
40 else if(pPoints
[i
].m_Curvetype
== CURVETYPE_SLOW
)
42 else if(pPoints
[i
].m_Curvetype
== CURVETYPE_FAST
)
47 else if (pPoints
[i
].m_Curvetype
== CURVETYPE_STEP
)
54 for(int c
= 0; c
< Channels
; c
++)
56 float v0
= fx2f(pPoints
[i
].m_aValues
[c
]);
57 float v1
= fx2f(pPoints
[i
+1].m_aValues
[c
]);
58 pResult
[c
] = v0
+ (v1
-v0
) * a
;
65 pResult
[0] = fx2f(pPoints
[NumPoints
-1].m_aValues
[0]);
66 pResult
[1] = fx2f(pPoints
[NumPoints
-1].m_aValues
[1]);
67 pResult
[2] = fx2f(pPoints
[NumPoints
-1].m_aValues
[2]);
68 pResult
[3] = fx2f(pPoints
[NumPoints
-1].m_aValues
[3]);
73 static void Rotate(CPoint
*pCenter
, CPoint
*pPoint
, float Rotation
)
75 int x
= pPoint
->x
- pCenter
->x
;
76 int y
= pPoint
->y
- pCenter
->y
;
77 pPoint
->x
= (int)(x
* cosf(Rotation
) - y
* sinf(Rotation
) + pCenter
->x
);
78 pPoint
->y
= (int)(x
* sinf(Rotation
) + y
* cosf(Rotation
) + pCenter
->y
);
81 void CRenderTools::RenderQuads(CQuad
*pQuads
, int NumQuads
, int RenderFlags
, ENVELOPE_EVAL pfnEval
, void *pUser
)
83 Graphics()->QuadsBegin();
84 float Conv
= 1/255.0f
;
85 for(int i
= 0; i
< NumQuads
; i
++)
87 CQuad
*q
= &pQuads
[i
];
89 float r
=1, g
=1, b
=1, a
=1;
91 if(q
->m_ColorEnv
>= 0)
94 pfnEval(q
->m_ColorEnvOffset
/1000.0f
, q
->m_ColorEnv
, aChannels
, pUser
);
102 if(a
< 0.01f
|| (q
->m_aColors
[0].a
< 0.01f
&& q
->m_aColors
[1].a
< 0.01f
&& q
->m_aColors
[2].a
< 0.01f
&& q
->m_aColors
[3].a
< 0.01f
))
105 if(Opaque
&& !(RenderFlags
&LAYERRENDERFLAG_OPAQUE
))
107 if(!Opaque
&& !(RenderFlags
&LAYERRENDERFLAG_TRANSPARENT
))
110 Graphics()->QuadsSetSubsetFree(
111 fx2f(q
->m_aTexcoords
[0].x
), fx2f(q
->m_aTexcoords
[0].y
),
112 fx2f(q
->m_aTexcoords
[1].x
), fx2f(q
->m_aTexcoords
[1].y
),
113 fx2f(q
->m_aTexcoords
[2].x
), fx2f(q
->m_aTexcoords
[2].y
),
114 fx2f(q
->m_aTexcoords
[3].x
), fx2f(q
->m_aTexcoords
[3].y
)
125 pfnEval(q
->m_PosEnvOffset
/1000.0f
, q
->m_PosEnv
, aChannels
, pUser
);
126 OffsetX
= aChannels
[0];
127 OffsetY
= aChannels
[1];
128 Rot
= aChannels
[2]/360.0f
*pi
*2;
131 IGraphics::CColorVertex Array
[4] = {
132 IGraphics::CColorVertex(0, q
->m_aColors
[0].r
*Conv
*r
, q
->m_aColors
[0].g
*Conv
*g
, q
->m_aColors
[0].b
*Conv
*b
, q
->m_aColors
[0].a
*Conv
*a
),
133 IGraphics::CColorVertex(1, q
->m_aColors
[1].r
*Conv
*r
, q
->m_aColors
[1].g
*Conv
*g
, q
->m_aColors
[1].b
*Conv
*b
, q
->m_aColors
[1].a
*Conv
*a
),
134 IGraphics::CColorVertex(2, q
->m_aColors
[2].r
*Conv
*r
, q
->m_aColors
[2].g
*Conv
*g
, q
->m_aColors
[2].b
*Conv
*b
, q
->m_aColors
[2].a
*Conv
*a
),
135 IGraphics::CColorVertex(3, q
->m_aColors
[3].r
*Conv
*r
, q
->m_aColors
[3].g
*Conv
*g
, q
->m_aColors
[3].b
*Conv
*b
, q
->m_aColors
[3].a
*Conv
*a
)};
136 Graphics()->SetColorVertex(Array
, 4);
138 CPoint
*pPoints
= q
->m_aPoints
;
142 static CPoint aRotated
[4];
143 aRotated
[0] = q
->m_aPoints
[0];
144 aRotated
[1] = q
->m_aPoints
[1];
145 aRotated
[2] = q
->m_aPoints
[2];
146 aRotated
[3] = q
->m_aPoints
[3];
149 Rotate(&q
->m_aPoints
[4], &aRotated
[0], Rot
);
150 Rotate(&q
->m_aPoints
[4], &aRotated
[1], Rot
);
151 Rotate(&q
->m_aPoints
[4], &aRotated
[2], Rot
);
152 Rotate(&q
->m_aPoints
[4], &aRotated
[3], Rot
);
155 IGraphics::CFreeformItem
Freeform(
156 fx2f(pPoints
[0].x
)+OffsetX
, fx2f(pPoints
[0].y
)+OffsetY
,
157 fx2f(pPoints
[1].x
)+OffsetX
, fx2f(pPoints
[1].y
)+OffsetY
,
158 fx2f(pPoints
[2].x
)+OffsetX
, fx2f(pPoints
[2].y
)+OffsetY
,
159 fx2f(pPoints
[3].x
)+OffsetX
, fx2f(pPoints
[3].y
)+OffsetY
);
160 Graphics()->QuadsDrawFreeform(&Freeform
, 1);
162 Graphics()->QuadsEnd();
165 void CRenderTools::RenderTilemap(CTile
*pTiles
, int w
, int h
, float Scale
, vec4 Color
, int RenderFlags
,
166 ENVELOPE_EVAL pfnEval
, void *pUser
, int ColorEnv
, int ColorEnvOffset
)
168 //Graphics()->TextureSet(img_get(tmap->image));
169 float ScreenX0
, ScreenY0
, ScreenX1
, ScreenY1
;
170 Graphics()->GetScreen(&ScreenX0
, &ScreenY0
, &ScreenX1
, &ScreenY1
);
171 //Graphics()->MapScreen(screen_x0-50, screen_y0-50, screen_x1+50, screen_y1+50);
173 // calculate the final pixelsize for the tiles
174 float TilePixelSize
= 1024/32.0f
;
175 float FinalTileSize
= Scale
/(ScreenX1
-ScreenX0
) * Graphics()->ScreenWidth();
176 float FinalTilesetScale
= FinalTileSize
/TilePixelSize
;
178 float r
=1, g
=1, b
=1, a
=1;
182 pfnEval(ColorEnvOffset
/1000.0f
, ColorEnv
, aChannels
, pUser
);
189 Graphics()->QuadsBegin();
190 Graphics()->SetColor(Color
.r
*r
, Color
.g
*g
, Color
.b
*b
, Color
.a
*a
);
192 int StartY
= (int)(ScreenY0
/Scale
)-1;
193 int StartX
= (int)(ScreenX0
/Scale
)-1;
194 int EndY
= (int)(ScreenY1
/Scale
)+1;
195 int EndX
= (int)(ScreenX1
/Scale
)+1;
197 // adjust the texture shift according to mipmap level
198 float TexSize
= 1024.0f
;
199 float Frac
= (1.25f
/TexSize
) * (1/FinalTilesetScale
);
200 float Nudge
= (0.5f
/TexSize
) * (1/FinalTilesetScale
);
202 for(int y
= StartY
; y
< EndY
; y
++)
203 for(int x
= StartX
; x
< EndX
; x
++)
208 if(RenderFlags
&TILERENDERFLAG_EXTEND
)
224 continue; // mx = w-1;
228 continue; // my = h-1;
233 unsigned char Index
= pTiles
[c
].m_Index
;
236 unsigned char Flags
= pTiles
[c
].m_Flags
;
239 if(Flags
&TILEFLAG_OPAQUE
)
241 if(RenderFlags
&LAYERRENDERFLAG_OPAQUE
)
246 if(RenderFlags
&LAYERRENDERFLAG_TRANSPARENT
)
255 int Px0
= tx
*(1024/16);
256 int Py0
= ty
*(1024/16);
257 int Px1
= Px0
+(1024/16)-1;
258 int Py1
= Py0
+(1024/16)-1;
260 float x0
= Nudge
+ Px0
/TexSize
+Frac
;
261 float y0
= Nudge
+ Py0
/TexSize
+Frac
;
262 float x1
= Nudge
+ Px1
/TexSize
-Frac
;
263 float y1
= Nudge
+ Py0
/TexSize
+Frac
;
264 float x2
= Nudge
+ Px1
/TexSize
-Frac
;
265 float y2
= Nudge
+ Py1
/TexSize
-Frac
;
266 float x3
= Nudge
+ Px0
/TexSize
+Frac
;
267 float y3
= Nudge
+ Py1
/TexSize
-Frac
;
269 if(Flags
&TILEFLAG_VFLIP
)
277 if(Flags
&TILEFLAG_HFLIP
)
285 if(Flags
&TILEFLAG_ROTATE
)
299 Graphics()->QuadsSetSubsetFree(x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
);
300 IGraphics::CQuadItem
QuadItem(x
*Scale
, y
*Scale
, Scale
, Scale
);
301 Graphics()->QuadsDrawTL(&QuadItem
, 1);
304 x
+= pTiles
[c
].m_Skip
;
307 Graphics()->QuadsEnd();
308 Graphics()->MapScreen(ScreenX0
, ScreenY0
, ScreenX1
, ScreenY1
);