#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
int stipple_index = 0;
COLOR32 stipples[] = { CYAN, CYAN, CYAN, CYAN, 0, 0, 0, 0 };
const int stipple_count = sizeof stipples / sizeof stipples[0];
void put_pixel_pattern( const int x, const int y )
{
stipple_index %= stipple_count;
if ( !stipples[ stipple_index ].argb )
{
stipple_index++;
return;
}
screen.put_pixel( x, y, stipples[ stipple_index++ ] );
}
inline int iabs( const int v )
{
const int mask = v >> ( sizeof( int ) * CHAR_BIT - 1 );
return ( v ^ mask ) - mask;
}
void draw_line_pattern( int x0, int y0, const int x1, const int y1 )
{
const int dx = x1 - x0;
const int dy = y1 - y0;
const int adx = iabs( dx );
const int ady = iabs( dy );
if( adx + ady == 0 ) return;
if( adx >= ady )
{
const int sx = dx >> 30 | 1;
const int sy = ( dy << 16 ) / adx;
y0 <<= 16;
while( x0 != x1 )
{
put_pixel_pattern( x0, y0 >> 16 );
x0 += sx;
y0 += sy;
}
}
else
{
const int sx = ( dx << 16 ) / ady;
const int sy = dy >> 30 | 1;
x0 <<= 16;
while( y0 != y1 )
{
put_pixel_pattern( x0 >> 16, y0 );
y0 += sy;
x0 += sx;
}
}
}
inline COLOR32 get_random_color()
{
return COLOR32( rand() % 256, rand() % 256, rand() % 256 );
}
#define M_PI 3.14159265358979323846
#define D2R(d) ( (d) * M_PI / 180.f ) // degree to radian
inline void scale( float& x, float& y, const float cx, const float cy,
const float scale_x, const float scale_y )
{
x = ( x - cx ) * scale_x + cx;
y = ( y - cy ) * scale_y + cy;
}
inline void rotate_cw( float& x, float& y, const float cx, const float cy,
const float radian )
{
const float x_cx = x - cx;
const float y_cy = y - cy;
const float cos_r = cos( radian );
const float sin_r = sin( radian );
x = x_cx * cos_r - y_cy * sin_r + cx;
y = x_cx * sin_r + y_cy * cos_r + cy;
}
void scene()
{
screen.clear( 0 );
static int skip;
static COLOR32 color;
stipple_index = skip++;
const float step = 0.07f;
float angle = 0.f;
float radius = 100.f;
for( int cx = -SCREEN_WIDTH; cx < SCREEN_WIDTH * 2; cx++ )
{
float x1 = cos( angle ) * radius + cx;
float y1 = -sin( angle ) * radius + SCREEN_HEIGHT / 2;
float x2 = cos( angle + step ) * radius + cx;
float y2 = -sin( angle + step ) * radius + SCREEN_HEIGHT / 2;
scale( x1, y1, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.25f, 1.f );
scale( x2, y2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0.25f, 1.f );
rotate_cw( x1, y1, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, D2R( 80.f ) );
rotate_cw( x2, y2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, D2R( 80.f ) );
draw_line_pattern( x1, y1, x2, y2 );
angle += step;
radius -= 0.05;
}
}
특정 좌표를 기준으로 한 가로 세로 스케일과,
특정 좌표를 기준으로 한 회전 변환 함수 예제다.
예제에서의 기준은 화면의 중심.
가로로 스프링을 만들고, 가로 스케일을 1/4 로 줄인 다음 80도 시계방향 회전을 시킨다.
마지막으로 원의 반지름을 줄여가서 나선형 패턴을 완성.
영점 이동과 원점 이동을 반복적으로 행하고 있다.
사실 영점 이동후, 스케일, 회전 처리를 하고 원점 이동을 하는게 이익이고,
여러 점들에 동일한 sin, cos 계산을 하고 있으니 불합리 하다.
여러 점들을 transform 할 수 있는 함수가 있으면 빠르겠지유?
벡터와 행렬을 이용한 transform 들의 구현을 설명해주면 좋지만,
기본적으로 설명할게 많아서 일단 가볍게 몸만 풀어본거다.
누구의 요청사항이어서 말이지 ^ㅡ^;

첫댓글 반지름을 1 / k^2 형태로 줄여나가게 하면 당연히 위가 빵빵하고 허리가 잘록하게 taping 된다. 원의 중심을 느린 폭으로 sin 이동 시켜주면 회오리가 꿈틀 꿈틀 허리춤을 추겠지?
저 각 점의 위치를 기준으로 gaussian_random 을 발생시키면 현실적인 입자계의 표현에 가까워지는 것.