#pragma once #include "dxstdafx.h" #include "d3ddefs.h" #include #include #include #include #include "vector4d.h" #include "color.h" #include "object.h" ObjectModel::ObjectModel() { this->offset=0; nvertices = ntexcoords = ntriangles = 0; device=NULL; loaded=false; vertexRotationClockwise=true; vertexDeclarationCreated=false; modelVertices=NULL; vertexBuffer=NULL; logFile=NULL; decl=NULL; D3DXMatrixIdentity(&transformMatrix); } ObjectModel::ObjectModel(int offset) { this->offset=offset; nvertices = ntexcoords = ntriangles = 0; device=NULL; vertexBuffer=NULL; loaded=false; modelVertices=NULL; logFile=NULL; decl=NULL; D3DXMatrixIdentity(&transformMatrix); } ObjectModel::~ObjectModel( ) { SAFE_RELEASE(decl); SAFE_RELEASE(vertexBuffer) if(modelVertices!=NULL){ GlobalFree((HGLOBAL)modelVertices); } SAFE_DELETE(logFile); } HRESULT ObjectModel::Render(bool renderToAtlas){ HRESULT hr; if(!isLoaded()){ return E_FAIL; } V_RETURN(device->SetVertexDeclaration(this->decl)) if(renderToAtlas){ if(this->isVertexRotationClockwise()){ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE)) } else{ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE)) } } else{ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW)) } V_RETURN(this->device->SetStreamSource(0,vertexBuffer,0,sizeof(D3DVERTEX_MODEL))) V_RETURN(this->device->DrawPrimitive(D3DPT_TRIANGLELIST,0,ntriangles)) return hr; } HRESULT ObjectModel::RenderWithFX(LPD3DXEFFECT m_pEffect,bool renderToAtlas,D3DXMATRIX modelview,D3DXMATRIX modelviewproj){ HRESULT hr; if(m_pEffect==NULL){ return E_POINTER; } if(!isLoaded()){ return E_FAIL; } V_RETURN(device->SetVertexDeclaration(this->decl)) if(renderToAtlas){ if(this->isVertexRotationClockwise()){ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW)) } else{ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW)) } } else{ V_RETURN(device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW)) } D3DXMATRIX mw; D3DXMATRIX mwp; D3DXMATRIX inverseWorldMatrix; D3DXMatrixIdentity(&mw); D3DXMatrixIdentity(&mwp); D3DXMatrixIdentity(&inverseWorldMatrix); D3DXMatrixMultiply(&mw,&transformMatrix,&modelview); D3DXMatrixMultiply(&mwp,&transformMatrix,&modelviewproj); D3DXMatrixInverse(&inverseWorldMatrix,NULL,&mw); V_RETURN(m_pEffect->SetMatrix("modelview",&mw)) V_RETURN(m_pEffect->SetMatrix("modelviewproj",&mwp)) V_RETURN(m_pEffect->SetMatrixTranspose("modelviewIT",&inverseWorldMatrix)) V_RETURN(this->device->SetStreamSource(0,vertexBuffer,0,sizeof(D3DVERTEX_MODEL))) V_RETURN(m_pEffect->CommitChanges()) V_RETURN(this->device->DrawPrimitive(D3DPT_TRIANGLELIST,0,ntriangles)) return S_OK; } void ObjectModel::AddVertex( float x, float y, float z ) { vertices[nvertices++] = Vector(x, y, z); } void ObjectModel::AddTexCoord( float u, float v ) { texcoords[ntexcoords++] = Vector(u, v, 0); } void ObjectModel::AddTriangle( int i1, int t1, int i2, int t2, int i3, int t3 ) { triangles[ntriangles++] = Triangle(i1, t1, i2, t2, i3, t3); } HRESULT ObjectModel::initDeviceObjects(LPDIRECT3DDEVICE9 device){ HRESULT hr; if(!isLoaded()){ return E_FAIL; } this->device=device; D3DVERTEXELEMENT9 _decl[]= { {0,0,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,0 }, {0,16,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,0 }, {0,32,D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,0 }, {0,40,D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,1 }, {0,52,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,2 }, {0,68,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,0 }, D3DDECL_END() }; hr=device->CreateVertexDeclaration(_decl,&decl); this->CreateD3DVertices(); V_RETURN(device->CreateVertexBuffer(sizeof(D3DVERTEX_MODEL)*ntriangles*3,D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX_MODEL,D3DPOOL_MANAGED,&vertexBuffer,NULL)); void* pData; vertexBuffer->Lock(0,sizeof(pData),(void**)&pData,0); memcpy(pData,getModelVertices(),sizeof(D3DVERTEX_MODEL)*ntriangles*3); vertexBuffer->Unlock(); return hr; } HRESULT ObjectModel::resetDeviceObjects(LPDIRECT3DDEVICE9 device){ HRESULT hr; if(!isLoaded()){ return E_FAIL; } SAFE_RELEASE(vertexBuffer); SAFE_RELEASE(decl); this->device=device; V_RETURN(device->CreateVertexBuffer(sizeof(D3DVERTEX_MODEL)*ntriangles*3,D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX_MODEL,D3DPOOL_MANAGED,&vertexBuffer,NULL)); void* pData; vertexBuffer->Lock(0,sizeof(pData),(void**)&pData,0); memcpy(pData,getModelVertices(),sizeof(D3DVERTEX_MODEL)*ntriangles*3); vertexBuffer->Unlock(); return hr; } D3DVERTEX_MODEL* ObjectModel::getModelVertices(){ return(modelVertices); } bool ObjectModel::isVertexRotationClockwise(){ return this->vertexRotationClockwise; } bool ObjectModel::isLoaded(){ return loaded; } void ObjectModel::CreateD3DVertices(){ if(loaded){ modelVertices=(D3DVERTEX_MODEL*)GlobalAlloc(GPTR,ntriangles*3*sizeof(D3DVERTEX_MODEL)); for(int i = 0; i < ntriangles; i++) { for(int j = 0; j < 3; j++) { if(j==0){ //Vertex v0 is passed to D3D vertex v0. modelVertices[i*3+j].fX=vertices[triangles[i].v[j]].x; modelVertices[i*3+j].fY=vertices[triangles[i].v[j]].y; modelVertices[i*3+j].fZ=vertices[triangles[i].v[j]].z; modelVertices[i*3+j].u1=texcoords[triangles[i].t[j]].x; modelVertices[i*3+j].v1=texcoords[triangles[i].t[j]].y; } if(j==1){ //Vertex v2 is passed to D3D vertex v1. modelVertices[i*3+j].fX=vertices[triangles[i].v[j+1]].x; modelVertices[i*3+j].fY=vertices[triangles[i].v[j+1]].y; modelVertices[i*3+j].fZ=vertices[triangles[i].v[j+1]].z; modelVertices[i*3+j].u1=texcoords[triangles[i].t[j+1]].x; modelVertices[i*3+j].v1=texcoords[triangles[i].t[j+1]].y; } if(j==2){ //Vertex v1 is passed to D3D vertex v2. modelVertices[i*3+j].fX=vertices[triangles[i].v[j-1]].x; modelVertices[i*3+j].fY=vertices[triangles[i].v[j-1]].y; modelVertices[i*3+j].fZ=vertices[triangles[i].v[j-1]].z; modelVertices[i*3+j].u1=texcoords[triangles[i].t[j-1]].x; modelVertices[i*3+j].v1=texcoords[triangles[i].t[j-1]].y; } modelVertices[i*3+j].fW=1.0f; /* modelVertices[i*3+j].colorRGBr=(float)RED(i+offset)/255.0f; modelVertices[i*3+j].colorRGBg=(float)GREEN(i+offset)/255.0f; modelVertices[i*3+j].colorRGBb=(float)BLUE(i+offset)/255.0f; */ modelVertices[i*3+j].colorRGBr=(float)i+offset; modelVertices[i*3+j].colorRGBa=0.0f; modelVertices[i*3+j].nX=triangles[i].normal.x; modelVertices[i*3+j].nY=triangles[i].normal.y; modelVertices[i*3+j].nZ=triangles[i].normal.z; modelVertices[i*3+j].nW=1.0f; modelVertices[i*3+j].u2=triangles[i].BRDF.R; modelVertices[i*3+j].v2=triangles[i].BRDF.G; modelVertices[i*3+j].w2=triangles[i].BRDF.B; modelVertices[i*3+j].u3=triangles[i].emission.R; modelVertices[i*3+j].v3=triangles[i].emission.G; modelVertices[i*3+j].w3=triangles[i].emission.B; modelVertices[i*3+j].a3=triangles[i].area/triangles[i].texarea; } } this->vertexDeclarationCreated=true; } } void ObjectModel::Load( char * fname, bool ccw, bool cw, bool islight, float su, float sv, float ou, float ov ) { this->vertexRotationClockwise=cw; FILE * ifile = fopen(fname, "r"); if ( !ifile ) return; char buffer[80]; if (!fgets(buffer, 80, ifile)) return; int match; int i=0; for( ; ; ) { char tempc=0; if(sscanf(buffer,"%c",&tempc)){ while((tempc!='v')&&(tempc!='f')){ if (!fgets(buffer, 80, ifile)) return; sscanf(buffer,"%c",&tempc); } } float x, y, z; match = sscanf(buffer, "v %f %f %f\n", &x, &y, &z); if (match != 3) break; AddVertex(x, y, z); if (!fgets(buffer, 80, ifile)) return; i++; } float maxu = -1, maxv = -1, minu = 1, minv = 1; for( ; ; ) { char tempc=0; if(sscanf(buffer,"%c",&tempc)){ while((tempc!='v')&&(tempc!='f')){ if (!fgets(buffer, 80, ifile)) return; sscanf(buffer,"%c",&tempc); } } float u, v, w; match = sscanf(buffer, "vt %f %f %f\n", &u, &v, &w); if (match != 3){ match = sscanf(buffer, "vt %f %f\n", &u, &v); if (match != 2) break; } if (maxu < u) maxu = u; if (maxv < v) maxv = v; if (minu > u) minu = u; if (minv > v) minv = v; AddTexCoord(u, v); if (!fgets(buffer, 80, ifile)) return; } for(int i = 0; i < ntexcoords; i++) { texcoords[i].x = (texcoords[i].x - minu)/(maxu - minu) * su + ou; texcoords[i].y = (texcoords[i].y - minv)/(maxv - minv) * sv + ov; } int c=0; for( ; ; ) { int i1, t1, i2, t2, i3, t3; char tempc=0; if(sscanf(buffer,"%c",&tempc)){ while((tempc!='v')&&(tempc!='f')){ if (!fgets(buffer, 80, ifile)) return; sscanf(buffer,"%c",&tempc); } } match = sscanf(buffer, "f %i/%i %i/%i %i/%i\n", &i1, &t1, &i2, &t2, &i3, &t3); if (match != 6) break; AddTriangle(i1-1, t1-1, i2-1, t2-1, i3-1, t3-1); Triangle& triang = triangles[ntriangles-1]; Vector& v1 = vertices[ triang.v[0] ], v2 = vertices[ triang.v[1] ], v3 = vertices[ triang.v[2] ]; triang.center = (v1 + v2 + v3)/3; triang.normal = (ccw) ? (v2 - v1) % (v3 - v1) : (v3 - v1) % (v2 - v1); triang.area = triang.normal.Length()/2; triang.normal.Normalize(); triang.up = (v3 - v1) % triang.normal; Vector& tp1 = texcoords[ triang.t[0] ], tp2 = texcoords[ triang.t[1] ], tp3 = texcoords[ triang.t[2] ]; Vector tnormal = (tp2 - tp1) % (tp3 - tp1); triang.texarea = tnormal.Length()/2; triang.BRDF = Color(0.74f/M_PI, 0.73f/M_PI, 0.34f/M_PI); triang.emission = Color(0.0f, 0.0f, 0.0f); if(strcmp("boxl6.obj",fname)==0){ if(triang.normal.x>0.9){ triang.BRDF = Color(0.64f/M_PI, 0.06f/M_PI, 0.04f/M_PI); } if(triang.normal.x<-0.9){ triang.BRDF = Color(0.34f/M_PI, 0.57f/M_PI, 0.69f/M_PI); } } /* if(strcmp("boxl6.obj",fname)==0){ triang.BRDF=Color(0.9f/M_PI,0.9f/M_PI,0.9f/M_PI); triang.emission = Color(0.1f, 0.1f, 0.1f); } */ if(strcmp("kiskocka6.obj",fname)==0){ triang.BRDF = Color(0.74f/M_PI, 0.73f/M_PI, 0.34f/M_PI); } if(strcmp("light.obj",fname)==0){ triang.BRDF = Color(0.74f/M_PI, 0.73f/M_PI, 0.34f/M_PI); if(triang.normal.y<-0.9){ triang.emission = Color(20.0f, 20.0f, 20.0f); } } /* if (islight && (ntriangles == 2291) ){ //1500 triang.emission = Color(250,250,250); } if (islight && (ntriangles == 2292) ){ //1500 triang.emission = Color(250,250,250); } */ /* if (islight && (ntriangles == 509) ){ //1500 triang.emission = Color(250,250,250); } if (islight && (ntriangles == 510) ){ //1500 triang.emission = Color(250,250,250); } if (islight && (ntriangles == 2399) ){ //1500 triang.emission = Color(250,250,250); } if (islight && (ntriangles == 2400) ){ //1500 triang.emission = Color(250,250,250); } */ if (!fgets(buffer, 80, ifile)) break; } surface_area = texsurface_area = 0; for(int i = 0; i < ntriangles; i++) { surface_area += triangles[i].area; texsurface_area += triangles[i].texarea; } loaded=true; } void ObjectModel::GetCenterTriangle( int i, Vector& center, Vector& normal, Vector& up ) { if(i>=ntriangles||i>=MAXTRIANGLES||i<0){ return; } /* logFile=fopen("log2.txt","a+" ); fprintf(logFile,"Shooter triangle index: %i \n Ntriangles %i\n",i,ntriangles); fclose(logFile); */ center = triangles[i].center; normal = triangles[i].normal; up = triangles[i].up; }