Thread: Summer Project Preview

  1. #16
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I have not gotten into pixel and/or vertex shaders yet. Looks pretty cool, though. Perhaps I need to order yet another book. Arghhhh.

    I'm very excited to see the progress of your engine and your 3D tree looks very good. What modeling program do you use??

  2. #17
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    I should probably come clean here. Rather than use pixel shaders or other graphic card involved techniques, im going an old school - cross card compatible shader system. Learning it requires no book.

    My model class has a vertex array, a triangle array, a group array, and a material array. I'll stay out of exactly how they use each other for now but heres what i do for shaders.
    When i render the mesh, I check the texture name of the material assigned to the mesh(group) if it has _shader_ keyword then I start a special drawing routine. First, I load the appropriate shader material (in the screenshot the texture is called shader_orange) and draw it to the screen. The texture mapping is affected by su, and sv coordinates that are kept in the shader struct and updated each render. This is where all the "shader work"is done. After that I simply continue to draw the model again. However now alpha transparency is used so that in the appropriate spots the shader shows through.

    CLIFF NOTES for understanding
    1) loop through the model and draw each mesh (group)
    2) if mesh material has _shader_ in the name, draw that group with the appropriate shader texture
    3) draw same mesh (group) again using alpha transparency
    4) viola a simulated shader system.


    Heres the code snippet (since I plan to release source any way) keep in mind this section of the code constantly gets revamped to allow for special rendering techniques but this version shows how shader works.

    Code:
    // in load model routine of my ms3d class
    	m_pShaders = new shaderFunc[1];
    	m_pShaders[0].smaterial = new Material[1];
    	m_pShaders[0].du = 0.002f;
    	m_pShaders[0].dv = 0.003f;
    	m_pShaders[0].su = 0.0f;
    	m_pShaders[0].sv = 0.0f;
                   // manualy done as i havent implimented creating this information from the level data yet
    			m_pMaterials[i].m_texture = 0;
    		m_pShaders[0].smaterial->m_texture = CreateTGA("data/textures/shader_orange.tga"); // temp, fixme
    		m_shader = true;
    
    
    // later in code
    
    
    void MS3DModel::shaderRender() {
    		GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D );
    		bool shaderused = false;
    		// Draw By Group
    		for ( int i = 0; i < m_numMeshes; i++ )
    		{
    			int materialIndex = m_pMeshes[i].m_materialIndex;
    			if ( materialIndex >= 0 )
    			{
    				glMaterialfv( GL_FRONT, GL_AMBIENT, m_pMaterials[materialIndex].m_ambient );
    				glMaterialfv( GL_FRONT, GL_DIFFUSE, m_pMaterials[materialIndex].m_diffuse );
    				glMaterialfv( GL_FRONT, GL_SPECULAR, m_pMaterials[materialIndex].m_specular );
    				glMaterialfv( GL_FRONT, GL_EMISSION, m_pMaterials[materialIndex].m_emissive );
    				glMaterialf( GL_FRONT, GL_SHININESS, m_pMaterials[materialIndex].m_shininess );
    
    				if ( m_pMaterials[materialIndex].m_texture > 0 )
    				{
    					glDisable(GL_BLEND);
    					glEnable(GL_DEPTH_TEST);
    					//glBlendFunc(GL_NONE, GL_NONE);
    					shaderused = true;
    					if((cinstr(m_pMaterials[materialIndex].m_pTextureFilename, "_shader") != -1) && (cinstr(m_pMaterials[materialIndex].m_pTextureFilename, "_alpha") != -1)){
    						// to utilize shader, first draw the shaded mesh with shader texture
    						// then draw over it with reguler text + alpha
    					m_pShaders[0].su = wrap(0.0f, 1.0f, m_pShaders[0].su + (m_pShaders[0].du*timeScale(60)));
    					m_pShaders[0].sv = wrap(0.0f, 1.0f, m_pShaders[0].sv + (m_pShaders[0].dv*timeScale(60)));
    
    					glBindTexture( GL_TEXTURE_2D, m_pShaders[0].smaterial->m_texture );
    					glEnable( GL_TEXTURE_2D );
    					glBegin( GL_TRIANGLES );
    					{
    							for ( int j = 0; j < m_pMeshes[i].m_numTriangles; j++ )
    							{
    								int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];
    								const Triangle* pTri = &m_pTriangles[triangleIndex];
    
    								for ( int k = 0; k < 3; k++ )
    								{
    									int index = pTri->m_vertexIndices[k];
    
    									glNormal3fv( pTri->m_vertexNormals[k] );
    									glTexCoord2f( pTri->m_s[k] + m_pShaders[0].su, pTri->m_t[k]+m_pShaders[0].sv);
    									//glVertex3fv( m_pVertices[index].m_location );
    									glVertex3f(m_pVertices[index].m_location[0] * m_Scale,
    												m_pVertices[index].m_location[1] * m_Scale,
    												m_pVertices[index].m_location[2] * m_Scale);
    								}
    							}
    					}
    					glEnd();
    
    						glDisable(GL_DEPTH_TEST);
    						glEnable(GL_BLEND);
    						glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    						//glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);			// Enable Alpha Blending (disable alpha testing)
    												
    
    					}else if(cinstr(m_pMaterials[materialIndex].m_pTextureFilename, "_alpha") != -1) {
    						//glDisable(GL_DEPTH_TEST);
    						glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);			// Enable Alpha Blending (disable alpha testing)
    						glEnable(GL_BLEND);	
    					} else {
    						glEnable(GL_DEPTH_TEST);
    						glDisable(GL_BLEND);
    					}
    				
    						glBindTexture( GL_TEXTURE_2D, m_pMaterials[materialIndex].m_texture );
    						glEnable( GL_TEXTURE_2D );
    					
    				}
    				else {
    					glDisable( GL_TEXTURE_2D );
    				}
    			}
    			else
    			{
    				glDisable( GL_TEXTURE_2D );
    			}
    			glEnable(GL_DEPTH_TEST);
    			glBegin( GL_TRIANGLE_STRIP );
    			{
    
    				for ( int j = 0; j < m_pMeshes[i].m_numTriangles; j++ )
    				{
    					int triangleIndex = m_pMeshes[i].m_pTriangleIndices[j];
    					const Triangle* pTri = &m_pTriangles[triangleIndex];
    
    					for ( int k = 0; k < 3; k++ )
    					{
    						int index = pTri->m_vertexIndices[k];
    
    						glNormal3fv( pTri->m_vertexNormals[k] );
    						glTexCoord2f( pTri->m_s[k], pTri->m_t[k] );
    						//glVertex3fv( m_pVertices[index].m_location );
    						glVertex3f(m_pVertices[index].m_location[0] * m_Scale,
    									m_pVertices[index].m_location[1] * m_Scale,
    									m_pVertices[index].m_location[2] * m_Scale);
    					}
    				}
    			}
    			glEnd();
    			
    		}
    		if ( texEnabled )
    			glEnable( GL_TEXTURE_2D );
    		else
    			glDisable( GL_TEXTURE_2D );
    			glDisable( GL_BLEND );
    };
    So I hope that explains my technique.

    As far as the models are concerned. I've manualy converted a few map models for Quake3 to ms3d format in Milkshape 3d. I'm using that as my model file type.
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

  3. #18
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    >> As far as the models are concerned. I've manualy converted a few map models for Quake3 to ms3d format in Milkshape 3d. I'm using that as my model file type.
    <<

    Whats the size difference like when doing that? Id imagin the ms3d would take up quite a bit more room.

  4. #19
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    Quote Originally Posted by Perspective
    >> As far as the models are concerned. I've manualy converted a few map models for Quake3 to ms3d format in Milkshape 3d. I'm using that as my model file type.
    <<

    Whats the size difference like when doing that? Id imagin the ms3d would take up quite a bit more room.
    49kb .md3 compared to 50kb .ms3d
    not as much loss as you'd expect huh?


    Any way, I've attached my first demo. It doesn't do a lot,but displays 4 primary parts of the engine so far.
    1.) ms3d model handling
    2.) alpha transparency
    3.) shader effects
    4.) liquid type model modifier

    All these effects are determined to be used by the texture name of the material the box uses. You'll notice its lava2_shader_alpha.tga, the lava part tells it to use liquid effect animation. the _shader part tells it to use a shader effect, and _alpha tells it to do alpha blending.

    I'm still working to sync liquid animations together, you'll notice a little discrepncy between boxes. Same thing for shader animations.

    Arrow keys do simple rotations so you can get a better view.
    Please let me know what FPS you are getting--AND your machine specs. Vid card, ghz processor, ram etc. . I'm interested in performance tweaks and Ill use the information to compare with in the next demo.

    Bewarned, this demo file contains the exe only. I'm not ready to release the source as it is far too messy. If you are too weary of exe only then dont bother getting the zip. Just a forewarning.

    Thanks for input (i hope).
    The image attached is for those that dont want to run the demo.

    demo: http://www.restmasszero.com/downloads/tbademo.zip
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

  5. #20
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Very nice! It looks really good so keep up the good work!

  6. #21
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    Quote Originally Posted by dbgt goten
    49kb .md3 compared to 50kb .ms3d
    not as much loss as you'd expect huh?
    <snip>
    yeah, thats pretty cool. Ill have to look into that. Did you buy ms3d or are you just using the demo version?

    Bewarned, this demo file contains the exe only.
    Im at work now [linux box] ill check out the demo when i get home.

    I'm not ready to release the source as it is far too messy. If you are too weary of exe only then dont bother getting the zip. Just a forewarning.

    Thanks for input (i hope).
    The image attached is for those that dont want to run the demo.

    demo: http://www.restmasszero.com/downloads/tbademo.zip
    i totaly know how you feel. Im always so self concious about releasing source that doesnt meet my (un-necessarily high) standards. Screenie looks nice though.

  7. #22
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    WOW!, thats very cool. I had no idea it was animated like that. very cool motion.

    ~560 fps
    1.4 Ghz P-M (Centrino) Laptop
    64 MB Radeon 9000
    1 GB RAM.

  8. #23
    mov.w #$1337,D0 Jeremy G's Avatar
    Join Date
    Nov 2001
    Posts
    704
    Game Flow update:

    Seeing as I just finnished implementing two major features of the game I thought I'd post and update.

    Update 1, loading maps:
    I took a page from Mago's skyroads book and added a few touches. It's a pretty similer map format with some pretty important changes. Heres a small (4 blocks) map to demonstrate the format:
    Code:
    SECTION_MAP
    
    MAPNAME run_intro
    MODELPATH data\models\
    TEXTUREPATH data\textures\
    
    SECTION_MODELINDEX
    
    MODELCOUNT 3
    MODEL 0 block.ms3d
    MODEL 1 wedge.ms3d
    MODEL 2 biwedge.ms3d
    
    SECTION_TEXTUREINDEX
    
    TEXTURECOUNT 3
    TEXTURE 0 industry\metal_block.tga
    TEXTURE 1 industry\metal_floor.tga
    TEXTURE 2 industry\metal_floor2.tga
    
    SECTION_CUSTOM_FORCE_LIST
    
    CUSTOMFORCE 0 // id
    0.0 0.0 0.0  // bx by bz
    10.0 10.0 10.0 // tx ty tz
    0.0 0.0 5.0 // fx fy fz
    
    SECTION_BLOCKLIST
    ROWS 1
    BLOCKS 8
    
    ROW
    BLOCK 0 0 0
    BLOCK 0 1 0
    BLOCK 0 2 0
    BLOCK 0 3 0
    
    ROW
    BLOCK 1 0 0
    BLOCK 1 1 0
    BLOCK 1 2 0
    BLOCK 1 3 0
    
    END_BLOCKS
    
    END_MAP
    SECTION_<type> marks off each section
    The first three lines are info about the map. The name, the model path, and the texture path. This will allow for map makers to keep their custom content in relative directories.

    The next section is the model index. It contains the path to each model, and an id for it. The map uses instances* of models, so a minimal ammount of media is loaded per map. Translation and rotation information is contained in the block structure.

    The next section is the texture index. Basicly the same as the model index, but for textures.

    The fourth section is a bit more complicated. It is where the custom forces I talked about earlier are stored. I added comments (//) to help explain them, the // arn't part of the file.
    First comes the command CUSTOMFORCE, it's unecessary but I added it to help divide up the information and make it more human readable (for hand editing). Immediatly after it is the id number. Each force has an index. The indexs are used to keep track of where it is in the array of custom forces. Since I forgot to mention it earlier, it works the same for texture and model indecies. On the next consecutive lines are the vectors of the bottom left, and top right corners. Customforces are confined into 3d cubes to ease their handling. The third consecutive line has the force vector that acts upon the player.

    In the last section, all the blocks are stored. They are very simple right now, only holding the texture index, row and column position. I'll be adding more parameters when I really start worry about mapping. Things like rotation for models, and individual face texture indices.

    User Inter Face Menu Update:
    I've finished adding in the menu system and along the way came up with a program flow method. Rather then writing a long if statement for what functions to call in the game loop I use CallBack functionality instead. When the game is initialized at run time, the main menu function is stored in the call back function pointer. Options for new game, load, resume, etc will update the callback to next appropriate function.

    Thus, while a menu is being displayed, the game loop will not be updating--and vice versa.

    Of course I'll be adding GUI functionality which will be ingame interface that overlays the screen and doesn't interfere with the game loop. Later on that.

    Heres a few code snippets for kicks and giggles.
    from ui and uimain.cpp
    Code:
    /*****************************************************************************************************
    // All UI Menus must be initiated with proper call back functions
    *****************************************************************************************************/
    void UIMenuInitialize() {
    	uimMain = new UIMenu(UICBMain); // main menu
    	uimMain->setColor( newVector(0.6f, 0.02f, 0.02f) ); // set bg color
    	uimMain->allocateItems(1); // one menu item
    	
    	// create a new menu item
    	UIMenuItemText *temp = new UIMenuItemText("PERIL ROADS", "Crown Title", -72);
    	temp->setColor( newVector(1.7f, 1.5f, 0.0f), newVector(1.0f, 0.0f, 0.0f), newVector(0.0f, 0.0f, 1.0f) );
    	temp->setPosition( newVector(0.00f, 0.0f, -5.0f) );
    	// and add  it to the main menu
    	uimMain->replaceItem(0,temp);
    	
    	// initialize other menus here
    	
    
    };
    
    //////////////////////////
    // UIMenu Call Back Main
    //////////////////////////
    void UICBMain() {
                    // pretty simple right now, huh?
    	uimMain->receive(0, 0, 0, 0);
    	uimMain->render();
    }
    from the load map function
    Code:
    	// load model info
    	if(cinstr(readbuffer, "SECTION_MODELINDEX") > -1) {
    		// number of models
    		readFile >> readbuffer;
    		if(cinstr(readbuffer, "MODELCOUNT") > -1) {
    			int nummodels = 0;
    			readFile >> nummodels;
    			// delete existing data
    			if(m_models)
    				delete[] m_models;
    			m_models = new MS3DModel[ nummodels ];
    			m_modelcount = nummodels;
    		}
    		
    		// model loading loop
    		while(true) {
    			readFile >> readbuffer;
    			if(cinstr(readbuffer, "MODEL") > -1) { // make sure we are getting model index info
    				int index = 0;
    				readFile >> index; // get the model index number
    				readFile >> readbuffer; // and get the (relative) path name
    			
    				char *fullpath = new char[512]; // create temporary storage for full path name
    
    				sprintf(fullpath, "%s%s", m_modelPath, readbuffer);
    				char *replacePath = new char[strlen(fullpath)+1]; // this will replace the model pointer, so it isn't deleted
    				memcpy(replacePath, fullpath, strlen(fullpath)+1);
    				m_models[index].setPath(replacePath); // save the path info
    				//MessageBox( NULL, replacePath, "INFO", MB_OK );
    				delete[] fullpath; // clean up
    
    			} else { break; }
    		}
    	}
    c++->visualc++->directx->opengl->c++;
    (it should be realized my posts are all in a light hearted manner. And should not be taken offense to.)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Movie preview project architecture help
    By kroiz in forum C# Programming
    Replies: 8
    Last Post: 09-20-2008, 03:09 AM
  2. Problem Displaying a Struct
    By rockstarpirate in forum C++ Programming
    Replies: 16
    Last Post: 05-05-2008, 09:05 AM
  3. Dynamic Binding
    By gpr1me in forum C++ Programming
    Replies: 1
    Last Post: 03-24-2006, 09:01 AM
  4. Game Independent Anti-cheat Project Needs Programmers
    By GIA Project Lea in forum Projects and Job Recruitment
    Replies: 3
    Last Post: 09-15-2005, 07:41 PM