MFC and OpenGL Programming Snippets Reference

Posted by Anonymous and classified in Computers

Written on in English with a size of 10.48 KB

MFC Metafile Operations

Metafile Handling: HENHMETAFILE fork; ENHMETAHEADER forkHeader; Constructor: fork = GetEnhMetaFile(_T("viljuska.emf"));

If the fork is not null:

if (fork != NULL)
{
    GetEnhMetaFileHeader(fork, sizeof(ENHMETAHEADER), &forkHeader);
}

Destructor:

if (met)
{
    DeleteEnhMetaFile(met);
    met = NULL;
}

Dimensions and Playback:

int w = forkHeader.rclBounds.right;
int h = forkHeader.rclBounds.bottom;
pDC->PlayMetaFile(fork, CRect(0, 0, w, h));

Saving Metafiles:

ONSAVE()
{
    CRect rect(0, 0, 1000, 1000);
    HDC hdcMeta = CreateEnhMetaFile(NULL, _T("img.emf"), &rect, _T("PUT\SLIKE"));
    if (hdcMeta) {
        CDC dc;
        dc.Attach(hdcMeta);
        dc.Rectangle();
        // ... 
        dc.Ellipse();
        HENHMETAFILE hmf = CloseEnhMetaFile(hdcMeta);
        DeleteEnhMetaFile(hmf);
    }
}

Anti-Flicker Techniques in MFC

CRect rect;
GetClientRect(&rect);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* oldbmp = memDC.SelectObject(&bmp);
int oldmode = memDC.SetGraphicsMode(GM_ADVANCED);
XFORM form;
memDC.GetWorldTransform(&form);
// ...
memDC.SetWorldTransform(&form);
memDC.SetGraphicsMode(oldmode);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(oldbmp);
memDC.DeleteDC();

BOOL CGDIView::OnEraseBkgnd(CDC* pDC) {
    return TRUE;
}

Keyboard Events and Transformations

OnKeyDown Event

afx_msg void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags) Ctrl + Shift + X

if (nChar == 'R' || nChar == 'r') {
    angle += 5;
    Invalidate();
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);

Supported Virtual Keys: VK_LEFT, Return, Space, Escape, Tab, 'A', Add, Subtract

Transformations

#define _USE_MATH_DEFINES
#include <cmath>

float toRad(float angle) {
    return angle * M_PI / 180;
}

void Translate(CDC* pDC, float x, float y, bool rightMultiply) {
    XFORM xform{1, 0, 0, 1, x, y};
    pDC->ModifyWorldTransform(&xform, rightMultiply ? MWT_RIGHTMULTIPLY : MWT_LEFTMULTIPLY);
}

// Rotate
float rad = toRad(angle);
// {cos(rad), sin(rad), -sin(rad), cos(rad), 0, 0}

// Scale
// {x, 0, 0, y}

// Mirror
// {x ? -1 : 1, 0, 0, y ? -1 : 1}

Draw Transparent Images

void DImage::DrawTransparent(CDC* pDC, DImage* pImage) {
    int w = pImage->Width();
    int h = pImage->Height();
    CRect rect(0, 0, w, h);
    CDC* srcDC = new CDC();
    srcDC->CreateCompatibleDC(pDC);
    CDC* dstDC = new CDC();
    dstDC->CreateCompatibleDC(pDC);
    CBitmap* src = new CBitmap();
    src->CreateCompatibleBitmap(pDC, w, h);
    CBitmap* dst = new CBitmap();
    dst->CreateBitmap(w, h, 1, 1, nullptr);
    CBitmap* srcOld = srcDC->SelectObject(src);
    CBitmap* dstOld = dstDC->SelectObject(dst);
    pImage->Draw(srcDC, rect, rect); // dest, target, source
    srcDC->SetBkColor(srcDC->GetPixel(0, 0));
    dstDC->BitBlt(0, 0, w, h, srcDC, 0, 0, SRCCOPY); // Copies color image to mono DC. All BkColor becomes WHITE, rest BLACK.
    srcDC->SetBkColor(RGB(0, 0, 0)); // Background black
    srcDC->SetTextColor(RGB(255, 255, 255)); // Text white
    srcDC->BitBlt(0, 0, w, h, dstDC, 0, 0, SRCAND); // Background becomes black
    pDC->BitBlt(0, 0, w, h, dstDC, 0, 0, SRCAND); // Creates black hole in object shape
    pDC->BitBlt(0, 0, w, h, srcDC, 0, 0, SRCPAINT); // Paints the object
    dstDC->SelectObject(dstOld);
    srcDC->SelectObject(srcOld);
    dstDC->DeleteDC();
    delete dstDC;
    srcDC->DeleteDC();
    delete srcDC;
    delete src;
    delete dst;
}

OpenGL Renderer Setup and Scene Management

Prepare Scene

glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

float amb[] = { 0.5, 0.5, 0.5, 1.0 };
float diff[] = { 1.0, 1.0, 1.0, 1.0 };
float spec[] = { 1.0, 1.0, 1.0, 1.0 };

glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diff);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diff);
glLightfv(GL_LIGHT1, GL_SPECULAR, spec);

texLamp = LoadTexture("lamp.jpg");
texBot = LoadTexture("bot.jpg");
texSide = LoadTexture("side.jpg");
texTop = LoadTexture("top.jpg");

Draw Scene

void CGLRenderer::DrawScene(CDC *pDC) {
    wglMakeCurrent(pDC->m_hDC, m_hrc);
    // -----------------------------
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
    float globalAmb[] = { 0.3, 0.3, 0.3, 1.0 };
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmb);
    
    float pos0[] = { 0.0, 0.0, 1.0, 0.0 };
    glLightfv(GL_LIGHT0, GL_POSITION, pos0);
    
    X = r * cos(toRad(ang)) * cos(angY);
    Z = r * sin(toRad(ang)) * cos(angY);
    Y = r * sin(angY);
    gluLookAt(X, Y, Z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    
    glTranslated(0.0, 150.0, 0.0);
    DrawEnvCube(300);
    glTranslated(0.0, -149.0, 0.0);
    DrawAxes();
    
    float pos1[] = { 0.0, 1.0, 1.0, 0.0 };
    glLightfv(GL_LIGHT1, GL_POSITION, pos1);
    DrawLamp();
    
    glFlush();
    SwapBuffers(pDC->m_hDC);
    // -----------------------------
    wglMakeCurrent(NULL, NULL);
}

Reshape and Destroy Scene

void CGLRenderer::Reshape(CDC *pDC, int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(50, (double)w / (double)h, 0.1, 2000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    wglMakeCurrent(NULL, NULL);
}

void CGLRenderer::DestroyScene(CDC *pDC) {
    wglMakeCurrent(pDC->m_hDC, m_hrc);
    // ... 
    glDeleteTextures(1, &texBot);
    glDeleteTextures(1, &texLamp);
    glDeleteTextures(1, &texSide);
    glDeleteTextures(1, &texTop);
    wglMakeCurrent(NULL, NULL);
    
    if (m_hrc) {
        wglDeleteContext(m_hrc);
        m_hrc = NULL;
    }
}

GluLookAt Configuration

  • eyeX, eyeY, eyeZ: Camera position (lens location).
  • centerX, centerY, centerZ: Target point the camera is looking at.
  • upX, upY, upZ: Camera rotation orientation (e.g., 0, 1, 0).
  • Axis Colors: X is Blue, Y is Red, Z is Green.

Load Texture

UINT CGLRenderer::LoadTexture(char* fileName) {
    UINT texID;
    DImage img;
    img.Load(CString(fileName));
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glGenTextures(1, &texID);
    glBindTexture(GL_TEXTURE_2D, texID);
    glTexParameteri(GL_TEXTURE_2D, TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, img.Width(), img.Height(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, img.GetDIBBits());
    
    return texID;
}

OpenGL 3D Primitive Shapes

Draw Sphere

void DrawSphere(float r, int nSeg) {
    float a1, a2, a3, c1, s1, c2, s2, c3, s3;
    for (int i = 0; i < nSeg; i++) {
        a1 = -1.57079f + i * 3.14159f / nSeg;
        a2 = a1 + 3.14159f / nSeg;
        s1 = sin(a1); c1 = cos(a1);
        s2 = sin(a2); c2 = cos(a2);
        glBegin(GL_QUAD_STRIP);
        for (int j = 0; j <= 2 * nSeg; j++) {
            a3 = j * 3.14159f / nSeg;
            s3 = sin(a3); c3 = cos(a3);
            glNormal3f(c1 * c3, s1, c1 * s3);
            glTexCoord2f((float)j / (2 * nSeg), (float)i / nSeg);
            glVertex3f(c1 * c3 * r, s1 * r, c1 * s3 * r);
            glNormal3f(c2 * c3, s2, c2 * s3);
            glTexCoord2f((float)j / (2 * nSeg), (float)(i + 1) / nSeg);
            glVertex3f(c2 * c3 * r, s2 * r, c2 * s3 * r);
        }
        glEnd();
    }
}

Draw Cylinder

void DrawCylinder(float r, float h, int nSeg) {
    float a, c, s, u;
    glBegin(GL_QUAD_STRIP); // Body
    for (int i = 0; i <= nSeg; i++) {
        a = 2.0f * M_PI * i / nSeg;
        c = cos(a);
        s = sin(a);
        u = (float)i / nSeg;
        glNormal3f(c, 0.0f, s);
        glTexCoord2f(u, 0.0f); 
        glVertex3f(c * r, -h / 2.0f, s * r);
        glTexCoord2f(u, 1.0f); 
        glVertex3f(c * r, h / 2.0f, s * r);
    }
    glEnd();
    
    glNormal3f(0.0f, 1.0f, 0.0f);
    glBegin(GL_TRIANGLE_FAN); // Top cap
    glTexCoord2f(0.5f, 0.5f);
    glVertex3f(0, h / 2.0f, 0);
    for (int i = 0; i <= nSeg; i++) {
        a = 2.0f * M_PI * i / nSeg;
        glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
        glVertex3f(cos(a) * r, h / 2.0f, sin(a) * r);
    }
    glEnd();
    
    glNormal3f(0.0f, -1.0f, 0.0f);
    glBegin(GL_TRIANGLE_FAN); // Bottom cap
    glTexCoord2f(0.5f, 0.5f);
    glVertex3f(0, -h / 2.0f, 0);
    for (int i = 0; i <= nSeg; i++) {
        a = -2.0f * 3.14159f * i / nSeg;
        glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
        glVertex3f(cos(a) * r, -h / 2.0f, sin(a) * r);
    }
    glEnd();
}

Draw Cone

void DrawCone(float r, float h, int nSeg) {
    float a, c, s, u;
    glBegin(GL_TRIANGLE_FAN); // Body
    glNormal3f(0.0f, 1.0f, 0.0f); // Approximate normal for the tip
    glTexCoord2f(0.5f, 1.0f);
    glVertex3f(0, h / 2.0f, 0); // Cone tip
    for (int i = 0; i <= nSeg; i++) {
        a = 2.0f * 3.14159f * i / nSeg;
        c = cos(a);
        s = sin(a);
        glNormal3f(c, h / r, s); // Normal tilted along cone side
        glTexCoord2f((float)i / nSeg, 0.0f);
        glVertex3f(c * r, -h / 2.0f, s * r);
    }
    glEnd();
    
    glNormal3f(0.0f, -1.0f, 0.0f);
    glBegin(GL_TRIANGLE_FAN); // Bottom cap
    glTexCoord2f(0.5f, 0.5f);
    glVertex3f(0, -h / 2.0f, 0);
    for (int i = 0; i <= nSeg; i++) {
        a = -2.0f * 3.14159f * i / nSeg;
        glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
        glVertex3f(cos(a) * r, -h / 2.0f, sin(a) * r);
    }
    glEnd();
}

Related entries: