void CMeshConverter::OptimiseGraphicsObject(void)
{
	int						i;
	int						j;
	ID3DXMesh*				pXMesh;
	CGraphicsPrimitive*		pcPrimitive;
	CVertexBufferExtended*	psVertexBuffer;
	void*					pvDestIndexBuffer;
	void*					pvDestVertexBuffer;
	void*					pvSrcIndexBuffer;
	void*					pvSrcVertexBuffer;
	int						iVertSize;
	DWORD*					pvAdjacency;
	int						iPrimitiveStart;
	int						iOldVertSize;
	int						iNumIndices;
	int						iOldVertexBufferIndex;
	int						iNumTriangles;
	void*					pvDestBaseIndexBuffer;
	SIndexBuffer*			psIndexBuffer;
	DWORD					iMeshOptions;

	mpcGraphicsObject->SortPrimitives();
	mpcGraphicsObject->Lock();
	psIndexBuffer = mpcGraphicsObject->GetIndexBuffer();
	iVertSize = 0;
	iNumIndices = 0;
	iOldVertexBufferIndex = 0;
	iNumTriangles = 0;
	iOldVertSize = 0;
	iMeshOptions = D3DXMESH_SYSTEMMEM;
	SetFlag((int*)&iMeshOptions, D3DXMESH_32BIT, psIndexBuffer->iIndexSize == 4);
	for (i = 0; i < mpcGraphicsObject->GetNumPrimitives(); i++)
	{
		pcPrimitive = mpcGraphicsObject->GetPrimitive(i);
		psVertexBuffer = mpcGraphicsObject->GetVertexBufferForIndex(pcPrimitive->miVertexBufferIndex);

		if (iOldVertSize != psVertexBuffer->iVertexSize)
		{
			if (iNumIndices != 0)
			{
				gcD3D.CreateMesh(iNumTriangles, iNumIndices, iMeshOptions, psVertexBuffer->iVertexFormat, &pXMesh);
				iVertSize = pXMesh->GetNumBytesPerVertex();
				pXMesh->LockIndexBuffer(D3DLOCK_NO_DIRTY_UPDATE, &pvDestBaseIndexBuffer);
				pXMesh->LockVertexBuffer(D3DLOCK_NO_DIRTY_UPDATE, &pvDestVertexBuffer);

				psVertexBuffer = mpcGraphicsObject->GetVertexBufferForIndex(iOldVertexBufferIndex);
				pvSrcVertexBuffer = psVertexBuffer->pvLockedBuffer;

				if (iVertSize != psVertexBuffer->iVertexSize)
				{
					gcLogger.Error("D3DX vertex size differs from expected size");
					break;
				}

				memcpy(pvDestVertexBuffer, pvSrcVertexBuffer, psVertexBuffer->iVertexSize * psVertexBuffer->iNumVerticies);

				pvDestIndexBuffer = pvDestBaseIndexBuffer;
				for (j = iPrimitiveStart; j < i; j++)
				{
					pcPrimitive = mpcGraphicsObject->GetPrimitive(j);
					pvSrcIndexBuffer = RemapSinglePointer(psIndexBuffer->pvLockedBuffer, 2 * pcPrimitive->miStartIndex);
					memcpy(pvDestIndexBuffer, pvSrcIndexBuffer, psIndexBuffer->iIndexSize * pcPrimitive->miNumVertices);
					pvDestIndexBuffer = RemapSinglePointer(pvDestIndexBuffer, pcPrimitive->miNumVertices);
				}

				pvAdjacency = (DWORD*)malloc(pcPrimitive->miNumPrimitives * 3 * sizeof(DWORD));
				pXMesh->GenerateAdjacency(0.0f, pvAdjacency);
				pXMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_DONOTSPLIT, pvAdjacency, NULL, NULL, NULL);
				free(pvAdjacency);

				pvDestIndexBuffer = pvDestBaseIndexBuffer;
				for (j = iPrimitiveStart; j < i; j++)
				{
					pcPrimitive = mpcGraphicsObject->GetPrimitive(j);
					pvSrcIndexBuffer = RemapSinglePointer(psIndexBuffer->pvLockedBuffer, 2 * pcPrimitive->miStartIndex);
					memcpy(pvSrcIndexBuffer, pvDestIndexBuffer, psIndexBuffer->iIndexSize * pcPrimitive->miNumVertices);
					pvDestIndexBuffer = RemapSinglePointer(pvDestIndexBuffer, pcPrimitive->miNumVertices);
				}

				memcpy(pvSrcVertexBuffer, pvDestVertexBuffer, psVertexBuffer->iVertexSize * psVertexBuffer->iNumVerticies);

				pXMesh->UnlockIndexBuffer();
				pXMesh->UnlockVertexBuffer();
				pXMesh->Release();
			}
			iPrimitiveStart = i;
			iNumIndices = 0;
			iOldVertexBufferIndex = pcPrimitive->miVertexBufferIndex;
		}
		else
		{
			iNumIndices += pcPrimitive->miNumVertices;
			iNumTriangles += pcPrimitive->miNumPrimitives;
			if (iOldVertexBufferIndex != pcPrimitive->miVertexBufferIndex)
			{
				gcUserError.Set("Primitive vertex buffer index is F****D!");
				break;
			}
		}
	}
	mpcGraphicsObject->Unlock();
}
void LODManager::Render(IDirect3DDevice9 *D3DDevice) {
  const char *meshpath =
    (lod == GRID_FARNEAR ? "landscape\\lod\\farnear\\" :
    (lod == GRID_FARFAR  ? "landscape\\lod\\farfar\\" :
			   "landscape\\lod\\farinf\\"));
  const char *textpath =
    (lod == GRID_FARNEAR ? "landscapelod\\generated\\farnear\\" :
    (lod == GRID_FARFAR  ? "landscapelod\\generated\\farfar\\" :
			   "landscapelod\\generated\\farinf\\"));

  int nativeminx = (GRID_SIZE * 32) + (Constants.Coordinates.x - GridDistantCount.Get());
  int nativeminy = (GRID_SIZE * 32) + (Constants.Coordinates.y - GridDistantCount.Get());
  int nativemaxx = (GRID_SIZE * 32) + (Constants.Coordinates.x + GridDistantCount.Get());
  int nativemaxy = (GRID_SIZE * 32) + (Constants.Coordinates.y + GridDistantCount.Get());

  /* y-axis has flipped rounding */
  nativeminx = (nativeminx / 32) - GRID_SIZE;
  nativeminy = (nativeminy / 32) - GRID_SIZE + 0;
  nativemaxx = (nativemaxx / 32) - GRID_SIZE;
  nativemaxy = (nativemaxy / 32) - GRID_SIZE + 0;

  int gridx = Constants.Coordinates.x / 32;
  int gridy = Constants.Coordinates.y / 32;
  for (int x = (gridx - extend); x <= (gridx + extend); x++)
  for (int y = (gridy - extend); y <= (gridy + extend); y++) {
    /* TODO: try radius, seems it's not a box */
    /* leave out Oblivion's native tiles */
    if ((x >= nativeminx) && (x <= nativemaxx) &&
	(y >= nativeminy) && (y <= nativemaxy))
      continue;
    /* leave out other LOD's inner tiles */
    if ((abs(gridx - x) <= inner) &&
	(abs(gridy - y) <= inner))
      continue;

    /* where are we? */
    const float TileOffset[4] = {x * TILE_DIM, y * TILE_DIM, 0, 0};

    /* filter outside-array coordinates */
    if (((GRID_OFFSET + y) >= 0) && ((GRID_OFFSET + y) < GRID_SIZE) &&
	((GRID_OFFSET + x) >= 0) && ((GRID_OFFSET + x) < GRID_SIZE)) {

      /* never seen, never attempted */
      if (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	/* TODO: 32 means 32x32 cells, in theory that can be different as well */
	char buf[256]; sprintf(buf, "%02d.%02d.%02d.32", WorldSpace, x * 32, y * 32);
	char pth[256]; strcpy(pth, meshpath); strcat(pth, buf); strcat(pth, ".x");

	/* no textures without mesh, but we can render texture-free */
	if ((MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	    MeshManager::GetSingleton()->LoadPrivateMesh(pth, MR_REGULAR)) != -1) {

	  if (ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	    strcpy(pth, textpath); strcat(pth, buf); strcat(pth, ".dds");
	    ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	      TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR);
	  }

	  if (NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) {
	    strcpy(pth, textpath); strcat(pth, buf); strcat(pth, "_fn.dds");
	    NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] =
	      TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR);
	  }

	  /* put the addresses */
	  ManagedMeshRecord    *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x] =    MeshManager::GetSingleton()->GetMesh   (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);
	  ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);
	  ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]);

	  /* failure to load all resources */
	  if (!mesh || !colr || !norm) {
	    if (mesh) mesh->Release();
	    if (colr) colr->Release();
	    if (norm) norm->Release();

	    MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;
	    ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;
	    NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1;

	    continue;
	  }

#if	defined(OBGE_GAMMACORRECTION)
	  /* remember DeGamma for this kind of texture */
	  static const bool PotDeGamma = true;
	  colr->GetTexture()->SetPrivateData(GammaGUID, &PotDeGamma, sizeof(PotDeGamma), 0);
#endif
	}
      }

      /* get the addresses */
      ManagedMeshRecord    *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x];
      ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x];
      ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x];

      ID3DXMesh *m;
      if (mesh && (m = (ID3DXMesh *)mesh->GetMesh())) {
#if 0
	DWORD FVF  = m->GetFVF();
	DWORD size = m->GetNumBytesPerVertex();
	DWORD numf = m->GetNumFaces();
	DWORD numv = m->GetNumVertices();

	IDirect3DIndexBuffer9 *pIB; m->GetIndexBuffer(&pIB);
	IDirect3DVertexBuffer9 *pVB; m->GetVertexBuffer(&pVB);

	D3DDevice->SetStreamSource(0, pVB, 0, size);
	D3DDevice->SetFVF(FVF);
	D3DDevice->SetTexture(0, colr->GetTexture());
	D3DDevice->SetTexture(1, norm->GetTexture());
	D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numv, 0, numf);
#endif

	D3DDevice->SetTexture(0, colr ? colr->GetTexture() : NULL);
	D3DDevice->SetTexture(1, norm ? norm->GetTexture() : NULL);

	D3DDevice->SetVertexShader(vShader[lod]);
	D3DDevice->SetPixelShader (pShader[lod]);
	D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

	m->DrawSubset(0);
      }
    }

    /* water-planes */
    D3DDevice->SetVertexShader(vShaderW);
    D3DDevice->SetPixelShader (pShaderW);
    D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

    D3DDevice->SetStreamSource(0, WaterVertex, 0, sizeof(WaterTile));
    D3DDevice->SetFVF(WATERTILEFORMAT);
    D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
  }

  const float TileOffset[4] = {0, 0, 0, 1};

  /* infini-plane */
  D3DDevice->SetVertexShader(vShaderW);
  D3DDevice->SetPixelShader (pShaderW);
  D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1);

  D3DDevice->SetStreamSource(0, InfiniteVertex, 0, sizeof(WaterTile));
  D3DDevice->SetFVF(WATERTILEFORMAT);
  D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
Esempio n. 3
0
void Scene::LoadFromXFile(string file, IDirect3DDevice9 *device)
{
    assert(device);

    ID3DXBuffer *material = nullptr;
    DWORD num_material = 0;
    ID3DXMesh *mesh = nullptr;

    HRESULT res = D3DXLoadMeshFromX(file.c_str(),     // pFilename
                                    D3DXMESH_DYNAMIC, // Options
                                    device,           // pD3DDevice
                                    nullptr,          // ppAdjacency
                                    &material,        // ppMaterials
                                    nullptr,          // ppEffectInstances
                                    &num_material,    // pNumMaterials
                                    &mesh);           // ppMesh
    if (FAILED(res))
    {
        Logger::GtLogError("load mesh from X file failed:%s", file.c_str());
        return;
    }
    assert(num_material == 1);
    D3DXMATERIAL *mat = static_cast<D3DXMATERIAL *>(material->GetBufferPointer());
    material_.ambient.r = mat->MatD3D.Ambient.r;
    material_.ambient.g = mat->MatD3D.Ambient.g;
    material_.ambient.b = mat->MatD3D.Ambient.b;
    material_.ambient.a = mat->MatD3D.Ambient.a;

    material_.diffuse.r = mat->MatD3D.Diffuse.r;
    material_.diffuse.g = mat->MatD3D.Diffuse.g;    
    material_.diffuse.b = mat->MatD3D.Diffuse.b;
    material_.diffuse.a = mat->MatD3D.Diffuse.a;

    material_.specular.r = mat->MatD3D.Specular.r;
    material_.specular.g = mat->MatD3D.Specular.g;
    material_.specular.b = mat->MatD3D.Specular.b;
    material_.specular.a = mat->MatD3D.Specular.a;

    material_.emissive.r = mat->MatD3D.Emissive.r;
    material_.emissive.g = mat->MatD3D.Emissive.g;
    material_.emissive.b = mat->MatD3D.Emissive.b;
    material_.emissive.a = mat->MatD3D.Emissive.a;

    material_.power = mat->MatD3D.Power;

    bool ret = texture_.Load(mat->pTextureFilename, device);
    assert(ret);
    material->Release();
    

    DWORD num_vertex = mesh->GetNumVertices();
    IDirect3DVertexBuffer9 *vertex_buffer = nullptr;
    res = mesh->GetVertexBuffer(&vertex_buffer);
    assert(SUCCEEDED(res));
    uint8 *vertex_data = nullptr;
    res = vertex_buffer->Lock(0, 0, reinterpret_cast<void **>(&vertex_data), D3DLOCK_READONLY);
    assert(SUCCEEDED(res));

    D3DVERTEXELEMENT9 vertex_elements[MAX_FVF_DECL_SIZE] = {0};
    res = mesh->GetDeclaration(vertex_elements);
    assert(SUCCEEDED(res));
    int offset_pos = 0;
    int offset_nor = 0;
    int offset_tex = 0;
    int vertex_size = mesh->GetNumBytesPerVertex();
    for (int i = 0; i < MAX_FVF_DECL_SIZE; ++i)
    {
        if (vertex_elements[i].Type == D3DDECLTYPE_UNUSED)
            break;
        if (vertex_elements[i].Usage == D3DDECLUSAGE_POSITION)
        {
            offset_pos = vertex_elements[i].Offset;
        }
        if (vertex_elements[i].Usage == D3DDECLUSAGE_NORMAL)
        {
            offset_nor =  vertex_elements[i].Offset;
        }
        if (vertex_elements[i].Usage == D3DDECLUSAGE_TEXCOORD)
        {
            offset_tex = vertex_elements[i].Offset;
        }
    }

    Primitive  verteies(num_vertex, nullptr, nullptr);
    for (int i = 0; i < num_vertex; ++i)
    {
        verteies.positions[i] = *reinterpret_cast<Vector3 *>(vertex_data + vertex_size * i + offset_pos);
        verteies.positions[i].Display();
        verteies.normals[i] = *reinterpret_cast<Vector3 *>(vertex_data + vertex_size * i + offset_nor);
        verteies.normals[i].Display();
        verteies.uvs[i] = *reinterpret_cast<Vector2 *>(vertex_data + vertex_size * i + offset_tex);
        verteies.uvs[i].Display();
    }
    primitive_ = verteies;

    vertex_buffer->Unlock();
    vertex_buffer->Release();
}