OpenGL: Howto about drawing 3D geometry ig perfectly (zbuffer, no ui overlay) menu

User Tag List

Results 1 to 6 of 6
  1. #1
    eLaps's Avatar Active Member
    Reputation
    34
    Join Date
    Sep 2007
    Posts
    123
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    OpenGL: Howto about drawing 3D geometry ig perfectly (zbuffer, no ui overlay)

    Hi,
    After some unsuccessful researches (see here), I finally managed to render stuff ingame, with or without the game's zbuffer (your choice), which wasn't covered (maybe even done) yet here so some of you could be interested, even if most of you use directx.

    The code (tasty C/C++ mix) I will explain with is written for linux so I give no guarantee for other systems, but it can be ported to Windows probably very easily (see here). The code is given here in its simplest form, for the purpose of the howto. It can obviously be greatly improved and made error-safe that's not the point. Current version is 3.5.5.12340.


    First of all, we will have to make our drawings at the right place: we don't want them to be over the interface. glDepthRange is called with (0.0f, 0.94f) when the game is drawing the world, and is called with (0.0f, 1.0f) when the ui is being drawn. Then we will just hook glDepthRange and draw there right before calling the first glDepthRange(0.0f, 1.0f) of each frame.
    Code:
    bool drawn = false;
    
    void glDepthRange(GLclampd nearVal, GLclampd farVal) {
    	static void (*real_glDepthRange)(GLclampd, GLclampd) = 0;
    	if (!real_glDepthRange)
    		real_glDepthRange = (void (*)(GLclampd, GLclampd))dlsym(RTLD_NEXT, "glDepthRange");
    
    	if (!drawn && farVal == 1) {
    		draw();
    		drawn = true;
    	}
    
    	real_glDepthRange(nearVal, farVal);
    }
    
    void hook_glXSwapBuffers(Display* _dpy, GLXDrawable _drawable) {
    	static void (*real)(Display*, GLXDrawable) = 0;
    	if (!real)
    		real = (void (*)(Display*, GLXDrawable))dlsym(RTLD_NEXT, "glXSwapBuffers");
    
    	if (!drawn)
    		draw();
            drawn = false;
    
    	real(_dpy, _drawable);
    }
    
    void (*glXGetProcAddressARB(const GLubyte* _procname))() {
    	static void* (*real)(const GLubyte*) = 0;
    	if (!real)
    		real = (void* (*)(const GLubyte*))dlsym(RTLD_NEXT, "glXGetProcAddressARB");
    
    	void* result = 0;
    	if (std::string("glXSwapBuffers") == (char*)_procname)
    		result = (void*)hook_glXSwapBuffers;
    
    	if (!result)
    		result = (void*)real(_procname);
    	return (void (*)())result;
    }

    If you use wine, a patch is required to hook glXSwapBuffers like this (explained here).


    Now what about the draw function?
    The original opengl context is constantly modified, which is a risk for us to attend unexpected results using it. Besides that, the other way is true (altering the original context in a bad way) and restoring every value isn't appealing. Creating our own opengl context seems to be the best solution.
    Every time we want to draw, we will make our context current, and switch back on the original when done.

    We have to enable the zbuffer, set the viewport and correctly place and orient the camera with the right fov, ratio, znear and zfar. gluPerspective and gluLookAt will do all the job for us.

    Most of the needed variables are in the camera structure given by CGWorldFrame__GetActiveCamera (source 1 & source 2, probably partially outdated tho).

    Besides that, a glScalef(2.0f, 2.0f, 1.0f) is needed to make our drawings match to the game's perspective and zbuffer. Don't ask how I've found that, just remove it and see by yourselves.

    The result:
    Code:
    #include <iostream>
    #include <GL/glx.h>
    #include <GL/glu.h>
    #include <GL/gl.h>
    #include <cmath>
    
    struct WoWCameraVTable {
    	uint32_t dontcare;
    	__attribute__((stdcall)) void (*get_forward_vector)(float*);    //(1)
    };
    
    struct WoWCamera {
    	WoWCameraVTable* vtable;
    	uint32_t dontcare0;
    	float x;
    	float y;
    	float z;
    	uint32_t dontcare1[9];
    	float znear;
    	float zfar;
    	float fov;
    	float ratio;
    };
    
    //void tetrahedron(bool orig_zbuffer, float x, float y, float z);
    
    void draw() {
    	
    	Display* dpy = glXGetCurrentDisplay();
    	GLXContext orig_ctx = glXGetCurrentContext();
    	GLXDrawable drawable = glXGetCurrentDrawable();
    
    	static GLXContext my_ctx = 0;
    	if (!my_ctx) {
    		//create our own opengl context
    		//this is the less portable part, but it's still very doable
    		int screen = -1;
    		glXQueryContext(dpy, orig_ctx, GLX_SCREEN, &screen);
    		int attribs[] = { GLX_FBCONFIG_ID, -1, None };
    		int dummy;
    		glXQueryContext(dpy, orig_ctx, GLX_FBCONFIG_ID, &attribs[1]);
    		GLXFBConfig* fb = glXChooseFBConfig(dpy, screen, attribs, &dummy);
    		XVisualInfo* vis = glXGetVisualFromFBConfig(dpy, *fb);
    		my_ctx = glXCreateContext(dpy, vis, 0, True);
    	}
    
    	glXMakeCurrent(dpy, drawable, my_ctx);
    	glEnable(GL_DEPTH_TEST);
    
    	uint32_t scr_w = 400, scr_h = 300;
    	glXQueryDrawable(dpy, drawable, GLX_WIDTH, &scr_w);
    	glXQueryDrawable(dpy, drawable, GLX_HEIGHT, &scr_h);
    	glViewport(0, 0, scr_w, scr_h);
    
    	WoWCamera* cam = ((WoWCamera* (*)())0x004F5960)(); //CGWorldFrame__GetActiveCamera
    	if (cam != 0) {    //use the camera to draw only if ingame
    		glMatrixMode(GL_PROJECTION);
    		glLoadIdentity();
    		gluPerspective(cam->fov * 180 / M_PI, cam->ratio, cam->znear, cam->zfar);
    
    		glMatrixMode(GL_MODELVIEW);
    		glLoadIdentity();
    		glScalef(2.0f, 2.0f, 1.0f);
    
    		float forward[3];
    		asm("movl %0, %%ecx;" : : "m" (cam));	//(2)
    		cam->vtable->get_forward_vector(forward);	//get forward vector
    		gluLookAt(cam->x, cam->y, cam->z, 
                              cam->x + forward[0], cam->y + forward[1], cam->z + forward[2], 
                              0, 0, 1);
    
    
                    //draw here
                    //tetrahedrons on the screenshots (Hammerfall camp, Arathi):
                    //tetrahedron(true, -960.739f, -3483.61f, 52.4689f);
                    //tetrahedron(false, -955.158f, -3492.94f, 52.3903f);
    
    
    	} else {
                //not ingame but you still can draw
                //just don't use CGWorldFrame__GetActiveCamera
            }
    
    	glXMakeCurrent(dpy, drawable, orig_ctx);
    }
    cam->vtable->get_forward_vector at (1) is actually a thiscall function and not a stdcall function, this (camerabase) being passed in ecx at (2). This is a workaround to respect the windows' thiscall calling convention under linux (explained here).

    Before finally drawing, call glDepthRange passing (0.0f, 0.94f) is you want your drawings to be hidden when behind an object of the game. Pass (0.0f, 0.1f) otherwise, then just draw.


    Here is the tetrahedron drawing function:
    Code:
    void tetrahedron(bool orig_zbuffer, float x, float y, float z) {
    	glDepthRange(0.0f, (orig_zbuffer) ? 0.94f : 0.1f);
    
    	glPushMatrix();
    	glTranslatef(x, y, z);
            glScalef(3.0f, 3.0f, 3.0f);
    	glBegin(GL_TRIANGLE_FAN);
    		glColor3ub(255,0,255);
    		glVertex3f(0.0f,0.0f,1.0f);
    
    		glColor3ub(255,0,0);
    		glVertex3f(1.0f,0.0f,0.0f);
    
    		glColor3ub(0,255,0);
    		glVertex3f(cos(2*M_PI/3),sin(2*M_PI/3),0);
    
    		glColor3ub(0,0,255);
    		glVertex3f(cos(-2*M_PI/3),sin(-2*M_PI/3),0);
    
    		glColor3ub(255,0,0);
    		glVertex3f(1.0f,0.0f,0.0f);
    	glEnd();
    	glPopMatrix();
    }
    Code:
    -4937.0f -936.0f 504.0f	//Ironforge, bridge in front of the AH
    5667.0f 675.0f 653.0f	//Dalaran, southern bank
    -8914.0f 624.0f 100.0f	//Stormwind bank
    1617.0f -4379.0f 13.0f	//Orgrimmar, bank


    Feel free to criticize, correct or complete.
    Last edited by eLaps; 08-11-2010 at 10:43 AM.

    OpenGL: Howto about drawing 3D geometry ig perfectly (zbuffer, no ui overlay)
  2. #2
    Sednogmah's Avatar Contributor
    Reputation
    129
    Join Date
    Oct 2009
    Posts
    158
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Excellent stuff! It's good to see a profound contribution once in a while.

  3. #3
    DarkLinux's Avatar Former Staff
    CoreCoins Purchaser Authenticator enabled
    Reputation
    1627
    Join Date
    May 2010
    Posts
    1,846
    Thanks G/R
    193/539
    Trade Feedback
    16 (100%)
    Mentioned
    7 Post(s)
    Tagged
    0 Thread(s)
    Looks simple when you put it that way, will need to try it out. Have not been to successful in the past with such 3D rendering. +Rep

  4. #4
    JuJuBoSc's Avatar Banned for scamming CoreCoins Purchaser
    Reputation
    1019
    Join Date
    May 2007
    Posts
    922
    Thanks G/R
    1/3
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you that was really interesting read ! +Rep

  5. #5
    audible83's Avatar Member
    Reputation
    4
    Join Date
    Jun 2008
    Posts
    48
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Impressive! Interesting! +1 rep.

    Wine offers a multitude of fancy things.

  6. #6
    berserk85's Avatar Member
    Reputation
    8
    Join Date
    Apr 2008
    Posts
    35
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    TNX this will be useful when i'll back to hack wow

Similar Threads

  1. [coding] OpenGL draw custom text?
    By qazz in forum WoW Memory Editing
    Replies: 29
    Last Post: 03-04-2009, 04:24 AM
  2. Something I've noticed about Rep
    By Shanaar in forum Community Chat
    Replies: 15
    Last Post: 07-12-2006, 01:20 AM
  3. questions about model editing
    By Avianar47 in forum World of Warcraft General
    Replies: 2
    Last Post: 07-08-2006, 09:41 PM
  4. Everything You Need To Know About Mining
    By Amedis in forum World of Warcraft Guides
    Replies: 4
    Last Post: 06-17-2006, 08:15 PM
  5. Your Thoughts about buying an Account
    By karokekid in forum World of Warcraft General
    Replies: 11
    Last Post: 06-12-2006, 04:25 PM
All times are GMT -5. The time now is 12:15 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search