bool PrepareTriangle(uint32_t dwV0, uint32_t dwV1, uint32_t dwV2) { SP_Timing(SP_Each_Triangle); bool textureFlag = (CRender::g_pRender->IsTextureEnabled() || gRSP.ucode == 6 ); InitVertex(dwV0, gRSP.numVertices, textureFlag); InitVertex(dwV1, gRSP.numVertices+1, textureFlag); InitVertex(dwV2, gRSP.numVertices+2, textureFlag); if(gRSP.numVertices == 0 && g_curRomInfo.bEnableTxtLOD && gRDP.otherMode.text_lod) { if( CRender::g_pRender->IsTexel1Enable() && CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->IsUsed(MUX_LODFRAC, MUX_MASK) ) { ComputeLOD(); } else { gRDP.LODFrac = 0; } } gRSP.numVertices += 3; status.dwNumTrisRendered++; return true; }
void CEngineSurface :: drawTexturedRect( int x0, int y0, int x1, int y1 ) { vpoint_t rect[2]; vpoint_t clippedRect[2]; InitVertex( rect[0], x0, y0, 0, 0 ); InitVertex( rect[1], x1, y1, 1, 1 ); // fully clipped? if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) return; VGUI_SetupDrawingImage( _drawColor ); VGUI_DrawQuad( &clippedRect[0], &clippedRect[1] ); }
void CEngineSurface :: drawFilledRect( int x0, int y0, int x1, int y1 ) { vpoint_t rect[2]; vpoint_t clippedRect[2]; if( _drawColor[3] >= 255 ) return; InitVertex( rect[0], x0, y0, 0, 0 ); InitVertex( rect[1], x1, y1, 0, 0 ); // fully clipped? if( !ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] )) return; VGUI_SetupDrawingRect( _drawColor ); VGUI_EnableTexture( false ); VGUI_DrawQuad( &clippedRect[0], &clippedRect[1] ); VGUI_EnableTexture( true ); }
/* ================ Model::ImportMD5 ================ */ Model *Model::ImportMD5( const char *filename, const char *filenameAnim ) { Lexer lexer(LEXER_NO_BOM_WARNING); if ( !lexer.LoadFile( filename ) ) return NULL; Model *model = new Model(true); int numJoints = -1; try { // MD5Version must be the first keyword lexer.ExpectToken( "MD5Version" ); int fileVersion = lexer.ReadInt(); if ( fileVersion != MD5_VERSION_DOOM3 && fileVersion != MD5_VERSION_QUAKEWARS ) lexer.Error( Format( "MD5Version is $*, should be $* or $*") << fileVersion << MD5_VERSION_DOOM3 << MD5_VERSION_QUAKEWARS ); const Token *token; String key; const char *p; bool inJointGroup = false; bool inMeshGroup = false; bool readMeshVerts = false; bool readMeshTris = false; int numMeshes = -1; int numVerts, vertIndex; int triCounter, indexCounter; int numWeights; MeshAnimated *mesh = NULL; int i, j, num; Vec3 vTemp; bool noAnimate = false; bool readVertexColor = false; Color vertexColor; ListEx<MD5Vertex> vertexList; ListEx<MD5Weight> weightList; while ( (token = lexer.ReadToken()) != NULL ) { p = token->GetString(); if ( !p || !*p ) continue; if ( inJointGroup ) { if ( *p == '}' ) { inJointGroup = false; continue; } lexer.ReadInt(); // unused ParseVector( lexer, &vTemp.x, 3 ); ParseVector( lexer, &vTemp.x, 3 ); } else if ( inMeshGroup ) { lexer.UnreadToken(); if ( readMeshVerts ) { if ( lexer.CheckToken( "numtris" ) ) { if ( numVerts != vertexList.Num() ) lexer.Error( Format("numVerts don't match: $*") << vertexList.Num() ); InitIndices( mesh, lexer.ReadInt() * 3 ); // numtris * 3 triCounter = 0; indexCounter = 0; readMeshVerts = false; readMeshTris = true; continue; } lexer.ExpectToken( "vert" ); vertIndex = lexer.ReadInt(); if ( vertIndex != vertexList.Num() ) lexer.Error( Format("Bad Vert Index, should be $*") << vertexList.Num() ); MD5Vertex &vertex = vertexList.Alloc(); ParseVector( lexer, &vertex.texCoord.x, 2 ); vertex.firstWeight = lexer.ReadInt(); vertex.lastWeight = lexer.ReadInt() + vertex.firstWeight - 1; if ( readVertexColor ) { // Currently we don't have use for vertex color.. // I haven't seen md5meshes with other values than ( 1 1 1 1 ) for vertexColor anyway.. ParseVector( lexer, &vertexColor.r, 4 ); } } else if ( readMeshTris ) { if ( lexer.CheckToken( "numweights" ) ) { numWeights = lexer.ReadInt(); weightList.CheckSize( numWeights ); readMeshTris = false; continue; } lexer.ExpectToken( "tri" ); if ( lexer.ReadInt() != triCounter ) lexer.Error( Format("Bad Tri Index, should be $*") << triCounter ); mesh->indices[indexCounter++] = lexer.ReadInt(); mesh->indices[indexCounter++] = lexer.ReadInt(); mesh->indices[indexCounter++] = lexer.ReadInt(); triCounter++; } else { if ( lexer.CheckToken( "}" ) ) { if ( numWeights != weightList.Num() ) lexer.Error( Format("numWeights doesn't match $*") << weightList.Num() ); // Convert vertices: num = vertexList.Num(); for( i=0; i<num; i++ ) { if ( i >= vertexList.Num() ) lexer.Error( "Vertex index out of range" ); const MD5Vertex &md5Vert = vertexList[i]; mesh->texCoords[i] = md5Vert.texCoord; Vertex &vInfo = mesh->vertices[i]; InitVertex( &vInfo, 1 + md5Vert.lastWeight - md5Vert.firstWeight ); vInfo.numWeights = 0; for ( j=md5Vert.firstWeight; j<=md5Vert.lastWeight; j++ ) { if ( j >= weightList.Num() ) lexer.Error( "Weight index out of range" ); const MD5Weight &md5Weight = weightList[j]; if ( md5Weight.jointIndex >= numJoints ) lexer.Error( "Weight joint index out of range" ); if ( md5Weight.bias == 0.0f ) continue; VertexWeight &weight = vInfo.weights[vInfo.numWeights++]; weight.boneId = md5Weight.jointIndex; weight.origin = md5Weight.origin; //weight.normal = md5Weight.normal; //! @todo calculate normal weight.influence = md5Weight.bias; } } inMeshGroup = false; continue; } lexer.ExpectToken( "weight" ); if ( lexer.ReadInt() != weightList.Num() ) lexer.Error( Format("Bad VertexWeight Index, should be $*") << weightList.Num() ); MD5Weight &weight = weightList.Alloc(); weight.jointIndex = lexer.ReadInt(); weight.bias = lexer.ReadFloat(); ParseVector( lexer, &weight.origin.x, 3 ); weight.origin *= MD5_MODEL_SCALE; } } else { if ( String::Icmp( p, "commandline" ) == 0 ) { // Skip value, we don't need it lexer.ReadToken(); } else if ( String::Icmp( p, "numJoints" ) == 0 ) { numJoints = lexer.ReadInt(); if ( numJoints > 0 ) { model->bones.SetGranularity( numJoints ); model->bones.CheckSize( numJoints ); } } else if ( String::Icmp( p, "numMeshes" ) == 0 ) { numMeshes = lexer.ReadInt(); if ( numMeshes <= 0 ) lexer.Error("Zero meshes"); model->meshes.SetGranularity( numMeshes ); model->meshes.CheckSize( numMeshes ); } else if ( String::Icmp( p, "joints" ) == 0 ) { if ( numJoints == -1 ) lexer.Error( "numJoins not set!" ); lexer.ExpectToken( "{" ); inJointGroup = true; } else if ( String::Icmp( p, "mesh" ) == 0 ) { if ( numMeshes == -1 ) lexer.Error( "numMeshes not set!" ); lexer.ExpectToken( "{" ); mesh = new MeshAnimated; model->meshes.Append(mesh); if ( fileVersion != MD5_VERSION_QUAKEWARS ) mesh->name = Format("mesh $*") << model->meshes.Num(); else { lexer.ExpectToken( "name" ); mesh->name = lexer.ReadString(); } lexer.ExpectToken( "shader" ); mesh->material = lexer.ReadString(); noAnimate = false; readVertexColor = false; if ( fileVersion == MD5_VERSION_QUAKEWARS ) { lexer.ExpectToken( "flags" ); lexer.ExpectToken( "{" ); while( !lexer.CheckToken("}") ) { if ( lexer.CheckToken("noAnimate") ) noAnimate = true; else if ( lexer.CheckToken("vertexColor") ) readVertexColor = true; else lexer.Error( Format("Unknown flag: '$*'") << lexer.ReadString() ); } } lexer.ExpectToken( "numverts" ); numVerts = lexer.ReadInt(); vertexList.Clear(); vertexList.CheckSize( numVerts ); weightList.Clear(); InitVertices( mesh, numVerts ); inMeshGroup = true; readMeshVerts = true; } else { lexer.Error( Format("Unexpected '$*'") << p ); } } } if ( inJointGroup || inMeshGroup || numJoints == -1 || numMeshes == -1 ) throw LexerError( LexerError::END_OF_FILE ); } catch( LexerError err ) { delete model; String errStr; err.ToString( errStr ); User::Error( ERR_LEXER_FAILURE, errStr.c_str(), filename ); return NULL; } if ( !ImportMD5AnimBaseFrame( filenameAnim, model ) ) return NULL; if ( numJoints != model->bones.Num() ) { delete model; User::Error( ERR_FILE_CORRUPT, "Number of Joints do not match", filename ); return NULL; } return model; }
/* ================ Model::ImportSKM ================ */ Model *Model::ImportSKM( const char *filename, const char *filenameAnim ) { if ( modelFS == NULL ) return NULL; File *file = modelFS->OpenRead( filename ); if( !file ) return NULL; Model *model = new Model(true); // Bones are all stored in skp files! if ( !ReadBonesFromSKP( filenameAnim, model ) ) return NULL; try { // Read header char header_id[4]; file->Read( header_id, 4 ); if ( String::Icmpn( header_id, SKMHEADER, String::Length(SKMHEADER) ) != 0 ) throw FileReadWriteError( "Not a skm file" ); uInt type = file->ReadUint(); uInt filesize = file->ReadUint(); uInt numbones = file->ReadUint(); uInt nummeshes = file->ReadUint(); uInt ofs_meshes = file->ReadUint(); if( type != SKM_MODELTYPE ) throw FileReadWriteError( Format("File has wrong type number ($* should be $*)" ) << type << SKM_MODELTYPE ); if( filesize > SKM_MAX_FILESIZE ) throw FileReadWriteError( Format("File has has wrong filesize ($* should be less than $*)" ) << filesize << SKM_MAX_FILESIZE ); if( nummeshes <= 0 ) throw FileReadWriteError("File has no meshes"); else if( nummeshes > SKM_MAX_MESHES ) throw FileReadWriteError("File has too many meshes"); if( numbones <= 0 ) throw FileReadWriteError("File has no bones"); else if( numbones > SKM_MAX_BONES ) throw FileReadWriteError("File has too many bones"); file->Seek( ofs_meshes, SEEK_SET ); if ( numbones != model->bones.Num() ) throw FileReadWriteError( Format("NumBones do not match : (SKP: $*, SKM: $*)\n" ) << model->bones.Num() << numbones ); mskmesh_t skm_mesh; uInt ofs_verts, ofs_texcoords, ofs_indices, ofs_references; long lastPos; for( int i=0; i<nummeshes; i++ ) { // Read Mesh Header file->Read( skm_mesh.shadername, SKM_MAX_NAME); file->Read( skm_mesh.name, SKM_MAX_NAME); skm_mesh.numverts = file->ReadUint(); skm_mesh.numtris = file->ReadUint(); skm_mesh.numreferences = file->ReadUint(); ofs_verts = file->ReadUint(); ofs_texcoords = file->ReadUint(); ofs_indices = file->ReadUint(); ofs_references = file->ReadUint(); lastPos = file->Tell(); // Print out some warnings if( skm_mesh.numverts <= 0 ) throw FileReadWriteError( Format("mesh $* has no vertexes" ) << i ); else if( skm_mesh.numverts > SKM_MAX_VERTS ) throw FileReadWriteError( Format("mesh $* has too many vertexes" ) << i ); if( skm_mesh.numtris <= 0 ) throw FileReadWriteError( Format("mesh $* has no indices" ) << i ); else if( skm_mesh.numtris > SKM_MAX_TRIS ) throw FileReadWriteError( Format("mesh $* has too many indices" ) << i ); if( skm_mesh.numreferences <= 0 ) throw FileReadWriteError( Format("mesh $* has no bone references" ) << i ); else if( skm_mesh.numreferences > SKM_MAX_BONES ) throw FileReadWriteError( Format("mesh $* has too many bone references" ) << i ); // Read Vertex Information file->Seek( ofs_verts, SEEK_SET ); MeshAnimated *mesh = new MeshAnimated; model->meshes.Append(mesh); mesh->name = skm_mesh.name; mesh->material = skm_mesh.shadername; InitVertices( mesh, skm_mesh.numverts ); for( int j = 0; j < skm_mesh.numverts; j++ ) { Vertex &vInfo = mesh->vertices[j]; InitVertex( &vInfo, file->ReadUint() ); for( int l = 0; l < vInfo.numWeights; l++ ) { VertexWeight &weight = vInfo.weights[l]; file->ReadFloatArray( &weight.origin.x, 3 ); weight.influence = file->ReadFloat(); file->ReadFloatArray( &weight.normal.x, 3 ); weight.boneId = file->ReadInt(); weight.origin *= SKM_MODEL_SCALE; } } file->Seek( ofs_texcoords, SEEK_SET ); file->ReadFloatArray( &mesh->texCoords[0].x, 2 * skm_mesh.numverts ); file->Seek( ofs_indices, SEEK_SET ); int num = skm_mesh.numtris * 3; InitIndices( mesh, num ); file->ReadIntArray( mesh->indices, num ); file->Seek( lastPos, SEEK_SET ); } file->Close(); return model; } catch( FileReadWriteError &err ) { file->Close(); delete model; User::Error( ERR_FILE_CORRUPT, Format("SKM: $*" ) << err.ToString(), filename ); return NULL; } }
//================================== // 函数:InitD3D( HWND ) // 目的:初始化Direct3D设备对象 // bool InitD3D() { //创建Direct3D对象 [用于获取硬件信息] g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D==NULL) return false; //检查是否支持硬件顶点处理 D3DCAPS9 caps; g_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps); int vp=0; if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) vp=D3DCREATE_HARDWARE_VERTEXPROCESSING; //硬件处理 else vp=D3DCREATE_SOFTWARE_VERTEXPROCESSING; //软件处理 //检查硬件支持的shader的版本 /* if(caps.VertexShaderVersion < D3DVS_VERSION(2,0)) deviceType = D3DDEVTYPE_REF; else deviceType = D3DDEVTYPE_HAL;*/ //设置D3DPRESENT_PARAMETERS结构 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp,sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //实时模式,默认是根据屏幕刷新频率 //创建Direct3D设备对象 [用于渲染图形] if( FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hwnd,vp,&d3dpp,&g_pd3dD)) ) return false; //设置观察和投影矩阵 setupViewAndProjMat(); //设置线性过滤 g_pd3dD->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); g_pd3dD->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); g_pd3dD->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT); g_pd3dD->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); //设置纹理寻址模式 g_pd3dD->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x00000000); g_pd3dD->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); g_pd3dD->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); g_pd3dD->SetSamplerState(1, D3DSAMP_BORDERCOLOR, 0x00000000); g_pd3dD->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); g_pd3dD->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); g_pd3dD->SetSamplerState(2, D3DSAMP_BORDERCOLOR, 0x00000000); g_pd3dD->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); g_pd3dD->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); //正反面都绘制 g_pd3dD->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); //关闭光照 g_pd3dD->SetRenderState( D3DRS_LIGHTING, FALSE ); //激活alpha混合 g_pd3dD->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); g_pd3dD->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); g_pd3dD->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dD->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); InitVertex(); //初始化顶点缓存,用于装载贴图 return true; }