截取3D游戏模型为obj格式

将任意d3d9游戏的模型截取到obj格式:工具下载

1,将d3d9.dll、snapconfig.cfg拷贝或覆盖到游戏运行目录(若果原先已经有d3d9.dll,则先备份以便还原)。

 

2,运行游戏,所有贴图和模型会自动保存到运行目录的SnapMesh文件夹。

 

3,截取完后不在使用时记得将d3d9.dll删除或还原,否则每次启动都会截取导致游戏很卡。

 

snapconfig.cfg配置说明:

[config]

snapAllTexture = 1           是否截取所有贴图(1是 包括ui贴图,0否 只截取模型贴图)

snapMesh = 1                  是否截取模型

snapMeshNormal = 0       是否截取模型法线信息

snapIndexSeprate = 0      是否将同一缓冲区的不同段作为不同的模型截取

minMeshTrigonNum = 1   截取模型最小面数

logDrawCount = 0            日志记录数

worldTransform = 0          是否使用世界坐标系(否则模型坐标系)

flipTexCoordV = 1            是否反转V向纹理坐标

 

原理:

新的d3d9.dll实际起到了一个代理作用。每次绘制结束保存纹理和模型。

这个技术同样适用于制作带有游戏内界面的外挂程序。

 

 

部分代码

 

void IDirect3DDevice9Proxy::ExportMesh()
{
if (G_Config.m_snapMesh==false)
{
return;
}
m_textureCoordExported=false;
m_pOriIDirect3DDevice9->GetIndices(&m_pIndexBuffer);
m_iIndexBuffer = (int)m_pIndexBuffer;

int startIndex = m_startIndex;
if (G_Config.m_snapIndexSeprate==0)
{
startIndex = 0;
}

MeshKey key;
key.m_indexPointer = m_iIndexBuffer;
key.m_startIndex = startIndex;
key.m_primcount = m_PrimitiveCount;

if (m_drawType==D_DrawIndexedPrimitive
&&m_pIndexBuffer
&&G_SavedMesh.find(key)==G_SavedMesh.end()
&&(m_PrimitiveType==D3DPT_TRIANGLELIST||m_PrimitiveType==D3DPT_TRIANGLESTRIP||m_PrimitiveType==D3DPT_TRIANGLEFAN)
&&m_PrimitiveCount>=G_Config.m_minMeshTrigonNum
)
{
IDirect3DBaseTexture9* pTexture=NULL;
int stage = 0;
bool get = false;
while (stage<8)
{
HRESULT res = m_pOriIDirect3DDevice9->GetTexture(stage,&pTexture);
if (pTexture)
{
get = true;
break;
}
//G_FastLog.OutputStr("GetTexture() return %d!",(int)res);
stage++;
}
if (pTexture==NULL)
{
int stage = 0;
while (stage<8)
{
pTexture = m_pTexture[stage];
if (pTexture)
{
break;
}
stage++;
}
}

//文理有可能已经释放重新加载,而指针值正巧相等,所以重新保存一下
if(pTexture)
{
char buf[256];
//texture在前以便排序剔除重复纹理
sprintf(buf,"SnapMesh\\%d_%d_%d.png",(int)pTexture,m_iIndexBuffer,startIndex);
D3DXSaveTextureToFile(buf, D3DXIFF_PNG, pTexture, NULL);
//GetTexture加了引用技术,需要释放
if(get)pTexture->Release();
}

G_SavedMesh.insert(key);
///
for (UINT i=0;i<8;i++)
{
m_pOriIDirect3DDevice9->GetStreamSource(i,m_pStreamVertexBuffer+i,m_streamOffsetInBytes+i,m_streamStride+i);
}

m_pIndexBuffer->GetDesc(&m_indexBufferDesc);

//if (SUCCEEDED(m_pOriIDirect3DDevice9->GetStreamSource(0,&pStreamData,&OffsetInBytes,&Stride)))
{
IDirect3DVertexDeclaration9* pDecl=NULL;
if (SUCCEEDED(m_pOriIDirect3DDevice9->GetVertexDeclaration(&pDecl)))
{
if (pDecl==NULL)
{
//DWORD FVF;
//if (SUCCEEDED(m_pOriIDirect3DDevice9->GetFVF(&FVF)))
//{
// if (FVF&D3DFVF_XYZ)
// {
// }
// if (FVF&D3DFVF_TEX2)
// {
// }
//}
}
else
{
if (SUCCEEDED(pDecl->GetDeclaration(m_vertexElement,&m_numElements)))
{
//
char buf[256];
sprintf(buf,"SnapMesh\\%d_%d.obj",m_iIndexBuffer,startIndex);
LogExportMesh();

//写入obj文件
FILE* file = fopen(buf, "wb");
if(file)
{
fprintf(file,"# exported by crapell engine!");
fprintf(file,"\n");
fprintf(file,"\n");

char mtlFileNameLocal[256];
sprintf(mtlFileNameLocal,"%d_%d.mtl",m_iIndexBuffer,startIndex);
fprintf(file,"mtllib %s ",mtlFileNameLocal);
fprintf(file,"\n");

fprintf(file,"# new object: ");
fprintf(file,"onemesh");
fprintf(file,"\n");

fprintf(file,"g ");
fprintf(file,"onemesh");
fprintf(file,"\n");

fprintf(file,"usemtl ");

char mtlFileName[256];
sprintf(mtlFileName,"SnapMesh\\%d_%d_%d.png",(int)pTexture,m_iIndexBuffer,startIndex);
fprintf(file,mtlFileName);
fprintf(file,"\n");

//输出数据流注释
for (UINT is=0;is<4;is++)
{
if (m_streamStride[is]<=0)
{
break;
}
fprintf(file,"# stream source[%d]: offset %d; stride %d;",is,m_streamOffsetInBytes[is],m_streamStride[is]);
fprintf(file,"\n");
}

fprintf(file,"# vertex element num:%d",m_numElements);
fprintf(file,"\n");

for (UINT e=0;e<m_numElements;e++)
{
int istream = m_vertexElement[e].Stream;
fprintf(file,"# vertex element[%d]:stream index%d; usage %s; type %s; offset in stride%d;",e,istream,usagename[m_vertexElement[e].Usage],typename_[m_vertexElement[e].Type],m_vertexElement[e].Offset);
fprintf(file,"\n");
if(istream==255)
{
break;
}
}

if(m_indexBufferDesc.Format==D3DFMT_INDEX32)
{
fprintf(file,"# %s: base vertex %d; vertex num %d; prim count %d; format INDEX32; type %s;",drawtypename[m_drawType],m_BaseVertexIndex,m_NumVertices,m_PrimitiveCount,primitivetypename_[m_PrimitiveType]);
}
else if(m_indexBufferDesc.Format==D3DFMT_INDEX16)
{
fprintf(file,"# %s: base vertex %d; vertex num %d; prim count %d; format INDEX16; type %s;",drawtypename[m_drawType],m_BaseVertexIndex,m_NumVertices,m_PrimitiveCount,primitivetypename_[m_PrimitiveType]);
}
else
{
fprintf(file,"# %s: base vertex %d; vertex num %d; prim count %d; format unknow; type %s;",drawtypename[m_drawType],m_BaseVertexIndex,m_NumVertices,m_PrimitiveCount,primitivetypename_[m_PrimitiveType]);
}
fprintf(file,"\n");

D3DXMATRIX wordMat;
D3DXMATRIX wordMatN;
D3DXVECTOR3 pos;
D3DXVECTOR4 res;
if (G_Config.m_worldTransform)
{
m_pOriIDirect3DDevice9->GetTransform(D3DTS_WORLD,&wordMat);
wordMatN = wordMat;
wordMatN(3,0)=0;
wordMatN(3,1)=0;
wordMatN(3,2)=0;
}

fprintf(file,"\n");

//输出真正数据
{
for (UINT e=0;e<m_numElements;e++)
{
int istream = m_vertexElement[e].Stream;
if(istream==255)
{
break;
}

if (m_vertexElement[e].Usage==D3DDECLUSAGE_POSITION)
{
char* bufferData;
if(SUCCEEDED(m_pStreamVertexBuffer[istream]->Lock(m_BaseVertexIndex * m_streamStride[istream], m_NumVertices * m_streamStride[istream], (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=m_BaseVertexIndex;pnum<m_NumVertices;pnum++)
{
fprintf(file,"v ");
switch (m_vertexElement[e].Type)
{
case D3DDECLTYPE_FLOAT3:
case D3DDECLTYPE_FLOAT4:
{
float* v = (float*)(bufferData+m_vertexElement[e].Offset);
if (G_Config.m_worldTransform)
{
pos.x = *v;
pos.y = *(v+1);
pos.z = *(v+2);
D3DXVec3Transform(&res,&pos,&wordMat);
fprintf(file,"%f %f %f ",res.x,res.y,res.z);
}
else
{
fprintf(file,"%f %f %f ",*v,*(v+1),*(v+2));
}
}
break;
//case D3DDECLTYPE_SHORT3:
case D3DDECLTYPE_SHORT4:
{
short* v = (short*)(bufferData+m_vertexElement[e].Offset);
if (G_Config.m_worldTransform)
{
pos.x = *v;
pos.y = *(v+1);
pos.z = *(v+2);
D3DXVec3Transform(&res,&pos,&wordMat);
fprintf(file,"%f %f %f ",res.x,res.y,res.z);
}
else
{
fprintf(file,"%f %f %f ",float(*v),float(*(v+1)),float(*(v+2)));
}
}
break;
}
bufferData+=m_streamStride[istream];
//fprintf(file,"# buffer pointer %d ",v);
fprintf(file,"\n");
}
}
m_pStreamVertexBuffer[istream]->Unlock();
//}
}
else if (m_vertexElement[e].Usage==D3DDECLUSAGE_NORMAL)
{
if (G_Config.m_snapMeshNormal)
{
char* bufferData;
if(SUCCEEDED(m_pStreamVertexBuffer[istream]->Lock(m_BaseVertexIndex * m_streamStride[istream], m_NumVertices * m_streamStride[istream], (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=m_BaseVertexIndex;pnum<m_NumVertices;pnum++)
{
fprintf(file,"vn ");
switch (m_vertexElement[e].Type)
{
case D3DDECLTYPE_FLOAT3:
case D3DDECLTYPE_FLOAT4:
{
float* v = (float*)(bufferData+m_vertexElement[e].Offset);
if (G_Config.m_worldTransform)
{
pos.x = *v;
pos.y = *(v+1);
pos.z = *(v+2);
D3DXVec3Transform(&res,&pos,&wordMatN);
fprintf(file,"%f %f %f ",res.x,res.y,res.z);
}
else
{
fprintf(file,"%f %f %f ",*v,*(v+1),*(v+2));
}
}
break;
//case D3DDECLTYPE_SHORT3:
case D3DDECLTYPE_SHORT4:
{
short* v = (short*)(bufferData+m_vertexElement[e].Offset);
if (G_Config.m_worldTransform)
{
pos.x = *v;
pos.y = *(v+1);
pos.z = *(v+2);
D3DXVec3Transform(&res,&pos,&wordMatN);
fprintf(file,"%f %f %f ",res.x,res.y,res.z);
}
else
{
fprintf(file,"%f %f %f ",float(*v),float(*(v+1)),float(*(v+2)));
}
}
case D3DDECLTYPE_SHORT4N:
{
short* v = (short*)(bufferData+m_vertexElement[e].Offset);
if (G_Config.m_worldTransform)
{
pos.x = *v;
pos.y = *(v+1);
pos.z = *(v+2);
D3DXVec3Transform(&res,&pos,&wordMatN);
fprintf(file,"%f %f %f ",res.x,res.y,res.z);
}
else
{
fprintf(file,"%f %f %f ",float(*v),float(*(v+1)),float(*(v+2)));
}
}
break;
}
bufferData+=m_streamStride[istream];
//fprintf(file,"# buffer pointer %d ",v);
fprintf(file,"\n");
}
}
m_pStreamVertexBuffer[istream]->Unlock();
//}
}
}
else if (m_vertexElement[e].Usage==D3DDECLUSAGE_TEXCOORD)
{
if (m_textureCoordExported==false)
{
m_textureCoordExported=true;
char* bufferData;
if(SUCCEEDED(m_pStreamVertexBuffer[istream]->Lock(m_BaseVertexIndex * m_streamStride[istream], m_NumVertices * m_streamStride[istream], (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=m_BaseVertexIndex;pnum<m_NumVertices;pnum++)
{
fprintf(file,"vt ");
switch (m_vertexElement[e].Type)
{
case D3DDECLTYPE_FLOAT3:
case D3DDECLTYPE_FLOAT4:
{
float* v = (float*)(bufferData+m_vertexElement[e].Offset);
if(G_Config.m_flipTexCoordV)
fprintf(file,"%f %f %f ",*v,1-*(v+1),*(v+2));
else
fprintf(file,"%f %f %f ",*v,*(v+1),*(v+2));
}
break;
case D3DDECLTYPE_FLOAT2:
{
float* v = (float*)(bufferData+m_vertexElement[e].Offset);
if(G_Config.m_flipTexCoordV)
fprintf(file,"%f %f %f ",*v,1-*(v+1),1.0f);
else
fprintf(file,"%f %f %f ",*v,*(v+1),1.0f);
}
break;
case D3DDECLTYPE_SHORT4:
{
short* v = (short*)(bufferData+m_vertexElement[e].Offset);
if(G_Config.m_flipTexCoordV)
fprintf(file,"%f %f %f ",(float)*v,(float)(1-*(v+1)),(float)*(v+2));
else
fprintf(file,"%f %f %f ",(float)*v,(float)(*(v+1)),(float)*(v+2));
}
break;
case D3DDECLTYPE_SHORT2:
{
short* v = (short*)(bufferData+m_vertexElement[e].Offset);
if(G_Config.m_flipTexCoordV)
fprintf(file,"%f %f %f ",(float)*v,(float)(1-*(v+1)),1);
else
fprintf(file,"%f %f %f ",(float)*v,(float)(*(v+1)),1);
}
break;
}
bufferData+=m_streamStride[istream];
fprintf(file,"\n");
}
}
m_pStreamVertexBuffer[istream]->Unlock();
}
}
}
}

//输出索引
int offset = -m_MinVertexIndex+m_BaseVertexIndex;
if (m_PrimitiveType==D3DPT_TRIANGLELIST)
{
if(m_indexBufferDesc.Format==D3DFMT_INDEX16)
{
short int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(short int), m_PrimitiveCount*3 * sizeof(short int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
(*bufferData)+offset+1,(*bufferData)+offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData+=3;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
else
{
int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(int), m_PrimitiveCount*3 * sizeof(int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
(*bufferData)+offset+1,(*bufferData)+offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData+=3;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
}
else if (m_PrimitiveType==D3DPT_TRIANGLESTRIP)
{
if(m_indexBufferDesc.Format==D3DFMT_INDEX16)
{
short int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(short int), (m_PrimitiveCount+2) * sizeof(short int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
(*bufferData)+offset+1,(*bufferData)+offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData++;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
else
{
int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(int), (m_PrimitiveCount+2) * sizeof(int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
(*bufferData)+offset+1,(*bufferData)+offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData++;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
}
else if (m_PrimitiveType==D3DPT_TRIANGLEFAN)
{
if(m_indexBufferDesc.Format==D3DFMT_INDEX16)
{
short int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(short int), (m_PrimitiveCount+2) * sizeof(short int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
offset+1,offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData++;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
else
{
int* bufferData;
if(SUCCEEDED(m_pIndexBuffer->Lock(m_startIndex * sizeof(int), (m_PrimitiveCount+2) * sizeof(int), (void**)&bufferData, D3DLOCK_READONLY)))
{
for (int pnum=0;pnum<m_PrimitiveCount;)
{
fprintf(file,"f ");
//v/t
fprintf(file,"%d/%d %d/%d %d/%d ",
offset+1,offset+1,
(*(bufferData+1))+offset+1,(*(bufferData+1)+offset+1),
(*(bufferData+2))+offset+1,(*(bufferData+2))+offset+1);
bufferData++;
pnum++;
fprintf(file,"\n");
}
m_pIndexBuffer->Unlock();
}
}
}
fclose(file);
}


材质
char mtlFileName[256];
sprintf(mtlFileName,"SnapMesh\\%d_%d.mtl",m_iIndexBuffer,startIndex);
FILE* mtlfile = fopen(mtlFileName, "wb");
if(mtlfile)
{
fprintf(mtlfile,"# exported by crapell engine!");
fprintf(mtlfile,"\n");
fprintf(mtlfile,"\n");
fprintf(mtlfile,"newmtl ");
sprintf(buf,"SnapMesh\\%d_%d_%d.png",(int)pTexture,m_iIndexBuffer,startIndex);
fprintf(mtlfile,buf);
fprintf(mtlfile,"\n");

fprintf(mtlfile,"Ka 1.0 1.0 1.0 ");
fprintf(mtlfile,"\n");

fprintf(mtlfile,"Kd 1.0 1.0 1.0 ");
fprintf(mtlfile,"\n");

fprintf(mtlfile,"Ks 0.2 0.2 0.2 ");
fprintf(mtlfile,"\n");

fprintf(mtlfile,"Ns 32 ");
fprintf(mtlfile,"\n");

fprintf(mtlfile,"map_Kd %s ",buf);
fprintf(mtlfile,"\n");

fprintf(mtlfile,"\n");
fclose(mtlfile);
}
}
pDecl->Release();
}
}
}

for (UINT i=0;i<8;i++)
{
m_pOriIDirect3DDevice9->GetStreamSource(i,m_pStreamVertexBuffer+i,m_streamOffsetInBytes+i,m_streamStride+i);
if (m_pStreamVertexBuffer[i])
{
m_pStreamVertexBuffer[i]->Release();
}
}
}
if (m_pIndexBuffer)
{
m_pIndexBuffer->Release();
}
m_drawType=D_DrawTriPatch;
}

void IDirect3DDevice9Proxy::ExportTexture(IDirect3DBaseTexture9* pTexture)
{
if (G_Config.m_snapAllTexture==false)
{
return;
}

char buf[256];
sprintf(buf,"SnapMesh\\texture\\%d.png",(int)pTexture);
if (G_SavedTexture.find((int)pTexture)==G_SavedTexture.end())
{
D3DXSaveTextureToFile(buf, D3DXIFF_PNG, pTexture, NULL);
G_SavedTexture.insert((int)pTexture);
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值