A
afurtado
Hi,
There is something preventing the drawing of a cube appear on the black window. Can you help me to find the bug?
There is something preventing the drawing of a cube appear on the black window. Can you help me to find the bug?
C:
#define _GNU_SOURCE
#include <windows.h>
#include <windowsx.h>
#include <stdbool.h>
#include <math.h>
#define WIDTH 800
#define HEIGHT 600
#define BMAPX 300
#define BMAPY 100
#define TRACKBALLSIZE (0.7f)
#define L 64
BITMAPINFO bmInfo;
HDC myCompatibleDC;
HBITMAP myBitmap;
HWND hwnd;
HPEN xPen;
// Trackball
boolean drag;
float lastQ[4];
float currQ[4];
int startx, starty;
float rotation[4];
float scale = 1;
void vzero(float *v)
{
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
}
void vset(float *v, float x, float y, float z)
{
v[0] = x;
v[1] = y;
v[2] = z;
}
void vsub(const float *src1, const float *src2, float *dst)
{
dst[0] = src1[0] - src2[0];
dst[1] = src1[1] - src2[1];
dst[2] = src1[2] - src2[2];
}
void vcopy(const float *v1, float *v2)
{
register int i;
for (i = 0 ; i < 3 ; i++)
v2[i] = v1[i];
}
void vcross(const float *v1, const float *v2, float *cross)
{
float temp[3];
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
vcopy(temp, cross);
}
float vlength(const float *v)
{
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
void vscale(float *v, float div)
{
v[0] *= div;
v[1] *= div;
v[2] *= div;
}
void vnormal(float *v)
{
vscale(v,1.0/vlength(v));
}
float vdot(const float *v1, const float *v2)
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}
void vadd(const float *src1, const float *src2, float *dst)
{
dst[0] = src1[0] + src2[0];
dst[1] = src1[1] + src2[1];
dst[2] = src1[2] + src2[2];
}
void axis_to_quat(float a[3], float phi, float q[4])
{
vcopy(a,q);
vnormal(q);
vscale(q,sin(phi/2.0));
q[3] = cos(phi/2.0);
}
void mul(float *r, float *a, float *b)
{
float w1 = a[0], x1 = a[1], y1 = a[2], z1 = a[3];
float w2 = b[0], x2 = b[1], y2 = b[2], z2 = b[3];
r[0] = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2; // Scalar (real) part
r[1] = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2; // i (x) component
r[2] = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2; // j (y) component
r[3] = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2; // k (z) component
}
/*
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
* if we are away from the center of the sphere.
*/
float tb_project_to_sphere(float r, float x, float y)
{
float d, t, z;
d = sqrt(x * x + y * y);
r = r * 0.7;
if (d < r)
{
// Inside sphere
z = sqrt(r * r - d * d);
}
else
{
// On hyperbola
t = r / 1.41421356237309504880;
z = (t * t) / d;
}
return z;
}
/*
* Arguments to this routine are in the range (-1.0 ... 1.0).
*/
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
{
float a[3]; /* Axis of rotation */
float phi; /* how much to rotate about axis */
float p1[3], p2[3], d[3];
float t;
if (p1x == p2x && p1y == p2y)
{
vzero(q);
q[3] = L;
return;
}
vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));
vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y));
vcross(p2,p1,a);
vsub(p1,p2,d);
t = vlength(d) / (2.0*TRACKBALLSIZE);
if (t > 1.0) t = L;
if (t < -1.0) t = -L;
phi = 2.0 * asin(t);
axis_to_quat(a, phi, q);
}
void normalize_quat(float q[4])
{
int i;
float mag;
mag = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
for (i = 0; i < 4; i++) q[i] /= mag;
}
void add_quats(float q1[4], float q2[4], float dest[4])
{
static int count=0;
float t1[4], t2[4], t3[4];
float tf[4];
vcopy(q1,t1);
vscale(t1,q2[3]);
vcopy(q2,t2);
vscale(t2,q1[3]);
vcross(q2,q1,t3);
vadd(t1,t2,tf);
vadd(t3,tf,tf);
tf[3] = q1[3] * q2[3] - vdot(q1,q2);
dest[0] = tf[0];
dest[1] = tf[1];
dest[2] = tf[2];
dest[3] = tf[3];
if (++count > 97)
{
count = 0;
normalize_quat(dest);
}
}
void scaleQuat(float quat[4])
{
int i;
for (i = 0; i < 4; i++)
{
quat[i] *= scale;
}
}
void rotateVector(float *rotated, float *rotation, float *object)
{
// Quaternion multiplication: q_rotated = q_rotation * q_object * q_conjugate(rotation)
float q_rotation[4] = { rotation[0], -rotation[1], -rotation[2], -rotation[3] };
float q_object[4] = { 0.0f, object[0], object[1], object[2] };
float q_conjugate[4] = { rotation[0], rotation[1], rotation[2], rotation[3] };
float temp1[4];
float temp2[4];
// Multiply q_rotation and q_object
mul(temp1, q_rotation, q_object);
// Multiply the result by q_conjugate
mul(temp2, temp1, q_conjugate);
// Extract the vector part from the result quaternion
rotated[0] = temp2[1];
rotated[1] = temp2[2];
rotated[2] = temp2[3];
}
void projLine(HDC hdc, float point1[3], float point2[3])
{
float rotated[3];
rotateVector(rotated, rotation, point1);
MoveToEx(hdc, WIDTH/2 + rotated[0]/2, HEIGHT/2 + rotated[1]/2, NULL);
rotateVector(rotated, rotation, point2);
LineTo(hdc, WIDTH/2 + rotated[0]/2, HEIGHT/2 + rotated[1]/2);
}
void drawModel2(HDC hdc)
{
SelectObject(hdc, xPen);
// Draw a simple cube
float p[8][3] = {
{-L, -L, -L},
{L, -L, -L},
{L, L, -L},
{-L, L, -L},
{-L, -L, L},
{L, -L, L},
{L, L, L},
{-L, L, L}
};
for (int i = 0; i < 4; i++)
projLine(hdc, p[i], p[(i + 1) % 4]);
for (int i = 0; i < 4; i++)
projLine(hdc, p[i + 4], p[((i + 1) % 4) + 4]);
for (int i = 0; i < 4; i++)
projLine(hdc, p[i], p[i + 4]);
}
void drawModel(HDC hdc)
{
SelectObject(hdc, xPen);
// Draw a simple cube
unsigned long shift, b[3] = { 0x00be6b3eUL, 0x0069635fUL, 0x0010b088UL };
float p[2][3];
p[0][0] = rand() % L - L/2;
p[0][1] = rand() % L - L/2;
p[0][2] = rand() % L - L/2;
p[1][0] = rand() % L - L/2;
p[1][1] = rand() % L - L/2;
p[1][2] = rand() % L - L/2;
projLine(hdc, p[0], p[1]);
for (int i = 0; i < 72; i++, shift >>= 1)
{
if(i % 24 == 0) shift = b[i/24];
p[(i / 3) % 2][i % 3] = (shift & 1) == 0 ? +L : -L;
if((i + 1) % 6 == 0) projLine(hdc, p[0], p[1]);
}
}
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
int x = GET_X_LPARAM(lparam);
int y = GET_Y_LPARAM(lparam);
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// GUI here
// Draw the 3d bitmap
HDC hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, myBitmap);
RECT rect;
rect.left = 0;
rect.bottom = 0;
rect.right = WIDTH;
rect.top = HEIGHT;
HBRUSH hbrBkGnd = CreateSolidBrush(RGB(0, 0, 0));
FillRect(hdcMem, &rect, hbrBkGnd);
DeleteObject(hbrBkGnd);
SetBkMode(hdcMem, TRANSPARENT);
drawModel(hdcMem);
drawModel2(hdcMem);
BitBlt(hdc, BMAPX, BMAPY, WIDTH, HEIGHT, hdcMem, 0, 0, SRCCOPY);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
break;
}
case WM_CREATE:
{
ZeroMemory(&bmInfo, sizeof(BITMAPINFO));
bmInfo.bmiHeader.biBitCount = 32;
bmInfo.bmiHeader.biHeight = HEIGHT;
bmInfo.bmiHeader.biPlanes = 1;
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth = WIDTH;
bmInfo.bmiHeader.biCompression = BI_RGB;
// Initial orientation
lastQ[0] = 1;
lastQ[1] = 0;
lastQ[2] = 0;
lastQ[3] = 0;
// Identity
currQ[0] = 1;
currQ[1] = 0;
currQ[2] = 0;
currQ[3] = 0;
drag = false;
xPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
// Start the rendering loop
SetTimer(hwnd, 1, 32, NULL); // 32 ms interval for approximately 60 FPS
break;
}
case WM_ERASEBKGND: // avoid flicker
return 1;
case WM_DESTROY:
ReleaseCapture();
DeleteObject(myBitmap) ;
DeleteDC(myCompatibleDC);
PostQuitMessage(0);
exit(0);
break;
case WM_LBUTTONDOWN:
startx = x;
starty = y;
drag = true;
SetCapture(hwnd);
return 0;
case WM_LBUTTONUP:
if (!drag)
break;
mul(lastQ, currQ, lastQ);
currQ[0] = 1;
currQ[1] = 0;
currQ[2] = 0;
currQ[3] = 0;
drag = false;
ReleaseCapture();
break;
case WM_MOUSEMOVE:
{
if (!drag)
break;
float dquat[4];
trackball (dquat,
(2.0*startx - WIDTH) / WIDTH,
(HEIGHT - 2.0*starty) / HEIGHT,
(2.0*x - WIDTH) / WIDTH,
(HEIGHT - 2.0*y) / HEIGHT);
add_quats (lastQ, dquat, currQ);
break;
}
case WM_TIMER:
InvalidateRect(hwnd, NULL, TRUE);
break;
default:
return DefWindowProc(hwnd, msg, wparam, lparam);
}
return lparam;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
CreateEvent(NULL, FALSE, FALSE, "Launching...");
WNDCLASS wc;
MSG msg;
ZeroMemory(&wc, sizeof(WNDCLASS));
//
wc.hInstance = hInstance;
wc.lpfnWndProc = MyWndProc;
wc.lpszClassName = "MYWNDCLASSNAME";
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
//
// Get the dimensions of the screen
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
RegisterClass(&wc);
hwnd = CreateWindow("MYWNDCLASSNAME", "C Forvm",
WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
20, 20, screenWidth - 500, screenHeight - 100, NULL, NULL, hInstance, NULL);
// Show window
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
// Create the bitmap child window
HDC hdc = GetDC(hwnd);
myBitmap = CreateCompatibleBitmap(hdc, WIDTH, HEIGHT);
HWND g_hBitmap = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP, BMAPX, BMAPY, 0, 0, hwnd, NULL, hInstance, NULL);
SendMessage(g_hBitmap, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)myBitmap);
ReleaseDC(hwnd, hdc);
InvalidateRect(hwnd, NULL, TRUE);
while(GetMessage(&msg, NULL, 0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}