Делаю следующее:
struct WARVERTEX { D3DXVECTOR3 p, n; FLOAT tu, tv; }; WARVERTEX pWarVerticesData[36]; struct Vertex { float pos[3]; float texCoord[2]; float normal[3]; float tangent[4]; }; Vertex pVerticesData[36]; IDirect3DVertexDeclaration9 *g_pVertexDecl; IDirect3DVertexBuffer9 *g_pVertexBuffer; D3DVERTEXELEMENT9 g_vertexElements[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, D3DDECL_END() }; void InitObjects( IDirect3DDevice9* pd3dDevice, IDirect3DVertexBuffer9* pVertexBuffer, DWORD baseVertexIndex) { WARVERTEX *pWarVertex1 = 0; WARVERTEX *pWarVertex2 = 0; WARVERTEX *pWarVertex3 = 0; Vertex *pVertex1 = 0; Vertex *pVertex2 = 0; Vertex *pVertex3 = 0; D3DXVECTOR4 tangent; pVertexBuffer->Lock( baseVertexIndex * sizeof( WARVERTEX), g_NumVertices * sizeof( WARVERTEX), ( LPVOID*)&pWarVerticesData, D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); for ( int i = 0; i < 36; i += 3) { pWarVertex1 = &pWarVerticesData[i]; pWarVertex2 = &pWarVerticesData[i + 1]; pWarVertex3 = &pWarVerticesData[i + 2]; pVertex1->pos[0] = pWarVertex1->p.x; pVertex1->pos[1] = pWarVertex1->p.y; pVertex1->pos[2] = pWarVertex1->p.z; pVertex1->texCoord[0] = pWarVertex1->tu; pVertex1->texCoord[1] = pWarVertex1->tv; pVertex1->normal[0] = pWarVertex1->n.x; pVertex1->normal[1] = pWarVertex1->n.y; pVertex1->normal[2] = pWarVertex1->n.z; pVertex2->pos[0] = pWarVertex2->p.x; pVertex2->pos[1] = pWarVertex2->p.y; pVertex2->pos[2] = pWarVertex2->p.z; pVertex2->texCoord[0] = pWarVertex2->tu; pVertex2->texCoord[1] = pWarVertex2->tv; pVertex2->normal[0] = pWarVertex2->n.x; pVertex2->normal[1] = pWarVertex2->n.y; pVertex2->normal[2] = pWarVertex2->n.z; pVertex3->pos[0] = pWarVertex3->p.x; pVertex3->pos[1] = pWarVertex3->p.y; pVertex3->pos[2] = pWarVertex3->p.z; pVertex3->texCoord[0] = pWarVertex3->tu; pVertex3->texCoord[1] = pWarVertex3->tv; pVertex3->normal[0] = pWarVertex3->n.x; pVertex3->normal[1] = pWarVertex3->n.y; pVertex3->normal[2] = pWarVertex3->n.z; } pVertexBuffer->Unlock( ); for ( int i = 0; i < 36; i += 3) { pVertex1 = &pVerticesData[i]; pVertex2 = &pVerticesData[i + 1]; pVertex3 = &pVerticesData[i + 2]; CalcTangentVector( pVertex1->pos, pVertex2->pos, pVertex3->pos, pVertex1->texCoord, pVertex2->texCoord, pVertex3->texCoord, pVertex1->normal, tangent); pVertex1->tangent[0] = tangent.x; pVertex1->tangent[1] = tangent.y; pVertex1->tangent[2] = tangent.z; pVertex1->tangent[3] = tangent.w; pVertex2->tangent[0] = tangent.x; pVertex2->tangent[1] = tangent.y; pVertex2->tangent[2] = tangent.z; pVertex2->tangent[3] = tangent.w; pVertex3->tangent[0] = tangent.x; pVertex3->tangent[1] = tangent.y; pVertex3->tangent[2] = tangent.z; pVertex3->tangent[3] = tangent.w; } if ( FAILED( pd3dDevice->CreateVertexBuffer( sizeof( Vertex) * 36, 0, 0, D3DPOOL_MANAGED, &g_pVertexBuffer, 0))) throw std::runtime_error( "Failed to create vertex buffer."); if ( FAILED( pd3dDevice->CreateVertexDeclaration( g_vertexElements, &g_pVertexDecl))) throw std::runtime_error( "Failed to create vertex declaration."); Vertex *pVertices = 0; if ( FAILED( g_pVertexBuffer->Lock( 0, 0, reinterpret_cast<void**>( &pVertices), 0))) throw std::runtime_error( "Failed to lock vertex buffer."); memcpy( pVertices, pVerticesData, sizeof( pVerticesData)); g_pVertexBuffer->Unlock( ); }
При запуске игра вылетает с фаталом. Это происходит из-за обращения к буферу pVertexBuffer, без него всё работает отлично. Может я что-то неправильно пишу в параметрах pVertexBuffer->Lock?
Подскажите, пожалуйста, что я не так делаю.
Данный буфер получаю отсюда:
STDMETHODIMP CDirect3DDevice8::SetStreamSource(THIS_ UINT StreamNumber, IDirect3DVertexBuffer8* pStreamData, UINT Stride) { IDirect3DVertexBuffer9* pStreamData9 = ( ( CDirect3DVertexBuffer8*)pStreamData)->ToNine( ); g_Stride=Stride; g_StreamNumber=StreamNumber; g_pStreamData9=pStreamData9; return D3D_OK;// pDevice9->SetStreamSource(StreamNumber, pStreamData9, 0, Stride); }
InitObjects(pDevice9, g_pStreamData9, g_baseVertexIndex);
И происходит ли чтения из буфера?
Изменил на это, теперь запускается, но ничего не рисует:
void InitObjects(IDirect3DDevice9* pd3dDevice, IDirect3DVertexBuffer9* pVertexBuffer, IDirect3DIndexBuffer9* pIndexBuffer, DWORD startIndex, DWORD primCount, DWORD baseVertexIndex) //InitObjects(IDirect3DDevice9* pd3dDevice, IDirect3DVertexBuffer9* pVertexBuffer, IDirect3DIndexBuffer9* pIndexBuffer, DWORD startIndex, DWORD baseVertexIndex) { WarVertex *pWarVertex1 = 0; WarVertex *pWarVertex2 = 0; WarVertex *pWarVertex3 = 0; //WORD* pIndicesData; Vertex *pVertex1 = 0; Vertex *pVertex2 = 0; Vertex *pVertex3 = 0; D3DXVECTOR4 tangent; D3DXVECTOR3 pos1; D3DXVECTOR3 pos2; D3DXVECTOR3 pos3; D3DXVECTOR3 n1; D3DXVECTOR3 n2; D3DXVECTOR3 n3; D3DXVECTOR2 tc1; D3DXVECTOR2 tc2; D3DXVECTOR2 tc3; pVertexBuffer->Lock( baseVertexIndex * sizeof( WarVertex), g_NumVertices * sizeof( WarVertex), ( LPVOID*)&pWarVerticesData, D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); //pIndexBuffer->Lock(startIndex * sizeof(WORD), // primCount * 3, // (LPVOID*)&pIndicesData, // D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); for ( int i = 0; i < 36; i += 3) { pWarVertex1 = &pWarVerticesData[i]; pWarVertex2 = &pWarVerticesData[i + 1]; pWarVertex3 = &pWarVerticesData[i + 2]; pos1.x = pWarVertex1->p.x; pos1.y = pWarVertex1->p.y; pos1.z = pWarVertex1->p.z; tc1.x = pWarVertex1->tu; tc1.y = pWarVertex1->tv; n1.x = pWarVertex1->n.x; n1.y = pWarVertex1->n.y; n1.z = pWarVertex1->n.z; pos2.x = pWarVertex2->p.x; pos2.y = pWarVertex2->p.y; pos2.z = pWarVertex2->p.z; tc2.x = pWarVertex2->tu; tc2.y = pWarVertex2->tv; n2.x = pWarVertex2->n.x; n2.y = pWarVertex2->n.y; n2.z = pWarVertex2->n.z; pos3.x = pWarVertex3->p.x; pos3.y = pWarVertex3->p.y; pos3.z = pWarVertex3->p.z; tc3.x = pWarVertex3->tu; tc3.y = pWarVertex3->tv; n3.x = pWarVertex3->n.x; n3.y = pWarVertex3->n.y; n3.z = pWarVertex3->n.z; } pVertexBuffer->Unlock( ); //pIndexBuffer->Unlock(); for ( int i = 0; i < 36; i += 3) { pVertex1 = &pVerticesData[i]; pVertex2 = &pVerticesData[i + 1]; pVertex3 = &pVerticesData[i + 2]; CalcTangentVector( pVertex1->pos, pVertex2->pos, pVertex3->pos, pVertex1->texCoord, pVertex2->texCoord, pVertex3->texCoord, pVertex1->normal, tangent); ////////////////////////////////////// pVertex1->pos[0] = pos1.x; pVertex1->pos[1] = pos1.y; pVertex1->pos[2] = pos1.z; pVertex1->texCoord[0] = tc1.x; pVertex1->texCoord[1] = tc1.y; pVertex1->normal[0] = n1.x; pVertex1->normal[1] = n1.y; pVertex1->normal[2] = n1.z; pVertex2->pos[0] = pos2.x; pVertex2->pos[1] = pos2.y; pVertex2->pos[2] = pos2.z; pVertex2->texCoord[0] = tc2.x; pVertex2->texCoord[1] = tc2.y; pVertex2->normal[0] = n2.x; pVertex2->normal[1] = n2.y; pVertex2->normal[2] = n2.z; pVertex3->pos[0] = pos3.x; pVertex3->pos[1] = pos3.y; pVertex3->pos[2] = pos3.z; pVertex3->texCoord[0] = tc3.x; pVertex3->texCoord[1] = tc3.y; pVertex3->normal[0] = n3.x; pVertex3->normal[1] = n3.y; pVertex3->normal[2] = n3.z; //////////////////////////////////////// pVertex1->tangent[0] = tangent.x; pVertex1->tangent[1] = tangent.y; pVertex1->tangent[2] = tangent.z; pVertex1->tangent[3] = tangent.w; pVertex2->tangent[0] = tangent.x; pVertex2->tangent[1] = tangent.y; pVertex2->tangent[2] = tangent.z; pVertex2->tangent[3] = tangent.w; pVertex3->tangent[0] = tangent.x; pVertex3->tangent[1] = tangent.y; pVertex3->tangent[2] = tangent.z; pVertex3->tangent[3] = tangent.w; } if ( FAILED( pd3dDevice->CreateVertexBuffer( sizeof( Vertex) * 36, 0, 0, D3DPOOL_MANAGED, &g_pVertexBuffer, 0))) throw std::runtime_error( "Failed to create vertex buffer."); if ( FAILED( pd3dDevice->CreateVertexDeclaration( g_vertexElements, &g_pVertexDecl))) throw std::runtime_error( "Failed to create vertex declaration."); Vertex *pVertices = 0; if ( FAILED( g_pVertexBuffer->Lock( 0, 0, reinterpret_cast<void**>( &pVertices), 0))) throw std::runtime_error( "Failed to lock vertex buffer."); memcpy( pVertices, pVerticesData, sizeof( pVerticesData)); g_pVertexBuffer->Unlock( ); }
Похоже проблема в несоответствии кол-ва вершин на входе. Как исправить?
Не могу понять, я ведь всё делаю правильно, но ничего не рисуется:
void InitObjects(IDirect3DDevice9* pd3dDevice, IDirect3DVertexBuffer9* pVertexBuffer) { WarVertex *pWarVertex1 = 0; WarVertex *pWarVertex2 = 0; WarVertex *pWarVertex3 = 0; WarVertex *pWarVertices = 0; Vertex *pVertex1 = 0; Vertex *pVertex2 = 0; Vertex *pVertex3 = 0; Vertex *pVertices = 0; D3DXVECTOR4 tangent; pVertexBuffer->Lock( 0, 0, reinterpret_cast<void**>( &pWarVertices), D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); g_pVertexBuffer->Lock( 0, 0, reinterpret_cast<void**>( &pVertices), 0) for ( int i = 0; i < 2145; i += 3) { pWarVertex1 = &pWarVertices[i]; pWarVertex2 = &pWarVertices[i + 1]; pWarVertex3 = &pWarVertices[i + 2]; pVertex1 = &pVertices[i]; pVertex2 = &pVertices[i + 1]; pVertex3 = &pVertices[i + 2]; pVertex1->pos[0] = pWarVertex1->p.x; pVertex1->pos[1] = pWarVertex1->p.y; pVertex1->pos[2] = pWarVertex1->p.z; pVertex1->texCoord[0] = pWarVertex1->tu; pVertex1->texCoord[1] = pWarVertex1->tv; pVertex1->normal[0] = pWarVertex1->n.x; pVertex1->normal[1] = pWarVertex1->n.y; pVertex1->normal[2] = pWarVertex1->n.z; pVertex2->pos[0] = pWarVertex2->p.x; pVertex2->pos[1] = pWarVertex2->p.y; pVertex2->pos[2] = pWarVertex2->p.z; pVertex2->texCoord[0] = pWarVertex2->tu; pVertex2->texCoord[1] = pWarVertex2->tv; pVertex2->normal[0] = pWarVertex2->n.x; pVertex2->normal[1] = pWarVertex2->n.y; pVertex2->normal[2] = pWarVertex2->n.z; pVertex3->pos[0] = pWarVertex3->p.x; pVertex3->pos[1] = pWarVertex3->p.y; pVertex3->pos[2] = pWarVertex3->p.z; pVertex3->texCoord[0] = pWarVertex3->tu; pVertex3->texCoord[1] = pWarVertex3->tv; pVertex3->normal[0] = pWarVertex3->n.x; pVertex3->normal[1] = pWarVertex3->n.y; pVertex3->normal[2] = pWarVertex3->n.z; CalcTangentVector( pVertex1->pos, pVertex2->pos, pVertex3->pos, pVertex1->texCoord, pVertex2->texCoord, pVertex3->texCoord, pVertex1->normal, tangent); pVertex1->tangent[0] = tangent.x; pVertex1->tangent[1] = tangent.y; pVertex1->tangent[2] = tangent.z; pVertex1->tangent[3] = tangent.w; pVertex2->tangent[0] = tangent.x; pVertex2->tangent[1] = tangent.y; pVertex2->tangent[2] = tangent.z; pVertex2->tangent[3] = tangent.w; pVertex3->tangent[0] = tangent.x; pVertex3->tangent[1] = tangent.y; pVertex3->tangent[2] = tangent.z; pVertex3->tangent[3] = tangent.w; } pVertexBuffer->Unlock( ); g_pVertexBuffer->Unlock( ); }
Пожалуйста, объясните, что я делаю не так?
ты не думаешь головой. Потому ничего не рисуется.
Если бы я не думал головой, то не смог бы это написать. А что Вы можете сказать по теме?
Рисовать объекты из инициализированной переменной получается, но читать данные вершин из оригинального буфера - нет.
Всё, получилось:


Провожу все вычисления при вызове функции CDirect3DDevice8::DrawIndexedPrimitive. Если смотреть на большое кол-во примитивов, то начинаются сильные подтормаживания, а затем и вовсе игра вылетает с ошибкой. По-хорошему нужно вызывать функцию InitObjects только в самом начале, при создании девайса, но как, если в это время ещё не известны переменные startIndex, numVertices, primCount, да и варкрафтовские буферы не созданы? И как вычислить оптимальный размер для создания буфера?
Вот код:
struct WarVertex { D3DXVECTOR3 p, n; FLOAT tu, tv; }; struct Vertex { float pos[3]; float texCoord[2]; float normal[3]; float tangent[4]; }; IDirect3DVertexDeclaration9 *g_pVertexDecl; IDirect3DVertexBuffer9 *g_pVertexBuffer; D3DVERTEXELEMENT9 g_vertexElements[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, D3DDECL_END() }; void InitObjects( IDirect3DDevice9* pd3dDevice, IDirect3DVertexBuffer9* pVertexBuffer, IDirect3DIndexBuffer9* pIndexBuffer, DWORD startIndex, DWORD numVertices, DWORD primCount, DWORD baseVertexIndex) { WarVertex *pWarVertex1 = 0; WarVertex *pWarVertex2 = 0; WarVertex *pWarVertex3 = 0; WarVertex *pWarVertices = 0; Vertex *pVertex1 = 0; Vertex *pVertex2 = 0; Vertex *pVertex3 = 0; Vertex *pVertices = 0; WORD* pWarIndicesData; D3DXVECTOR4 tangent; pVertexBuffer->Lock( baseVertexIndex * sizeof( WarVertex), numVertices * sizeof( WarVertex), ( LPVOID*)&pWarVertices, D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); pIndexBuffer->Lock( startIndex * sizeof( WORD), primCount * 3, ( LPVOID*)&pWarIndicesData, D3DLOCK_DONOTWAIT | D3DLOCK_READONLY | D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE); g_pVertexBuffer->Lock( baseVertexIndex * sizeof( Vertex), numVertices * sizeof( Vertex), ( LPVOID*)&pVertices, 0); for ( DWORD i = 0; i < primCount; i++) { WORD wFace0 = pWarIndicesData[3 * i + 0]; WORD wFace1 = pWarIndicesData[3 * i + 1]; WORD wFace2 = pWarIndicesData[3 * i + 2]; pWarVertex1 = &pWarVertices[wFace0]; pWarVertex2 = &pWarVertices[wFace1]; pWarVertex3 = &pWarVertices[wFace2]; pVertex1 = &pVertices[wFace0]; pVertex2 = &pVertices[wFace1]; pVertex3 = &pVertices[wFace2]; pVertex1->pos[0] = pWarVertex1->p.x; pVertex1->pos[1] = pWarVertex1->p.y; pVertex1->pos[2] = pWarVertex1->p.z; pVertex1->texCoord[0] = pWarVertex1->tu; pVertex1->texCoord[1] = pWarVertex1->tv; pVertex1->normal[0] = pWarVertex1->n.x; pVertex1->normal[1] = pWarVertex1->n.y; pVertex1->normal[2] = pWarVertex1->n.z; pVertex2->pos[0] = pWarVertex2->p.x; pVertex2->pos[1] = pWarVertex2->p.y; pVertex2->pos[2] = pWarVertex2->p.z; pVertex2->texCoord[0] = pWarVertex2->tu; pVertex2->texCoord[1] = pWarVertex2->tv; pVertex2->normal[0] = pWarVertex2->n.x; pVertex2->normal[1] = pWarVertex2->n.y; pVertex2->normal[2] = pWarVertex2->n.z; pVertex3->pos[0] = pWarVertex3->p.x; pVertex3->pos[1] = pWarVertex3->p.y; pVertex3->pos[2] = pWarVertex3->p.z; pVertex3->texCoord[0] = pWarVertex3->tu; pVertex3->texCoord[1] = pWarVertex3->tv; pVertex3->normal[0] = pWarVertex3->n.x; pVertex3->normal[1] = pWarVertex3->n.y; pVertex3->normal[2] = pWarVertex3->n.z; CalcTangentVector( pVertex1->pos, pVertex2->pos, pVertex3->pos, pVertex1->texCoord, pVertex2->texCoord, pVertex3->texCoord, pVertex1->normal, tangent); pVertex1->tangent[0] = tangent.x; pVertex1->tangent[1] = tangent.y; pVertex1->tangent[2] = tangent.z; pVertex1->tangent[3] = tangent.w; pVertex2->tangent[0] = tangent.x; pVertex2->tangent[1] = tangent.y; pVertex2->tangent[2] = tangent.z; pVertex2->tangent[3] = tangent.w; pVertex3->tangent[0] = tangent.x; pVertex3->tangent[1] = tangent.y; pVertex3->tangent[2] = tangent.z; pVertex3->tangent[3] = tangent.w; } pVertexBuffer->Unlock( ); pIndexBuffer->Unlock( ); g_pVertexBuffer->Unlock( ); }
Создание буфера:
CDirect3DDevice8::CDirect3DDevice8(IDirect3DDevice9* device, CDirect3D8* d3d) : pDevice9( device) , pDirect3D8( d3d) , zBufferDiscardingEnabled( FALSE) , g_baseVertexIndex( 0) { pDevice9->GetCreationParameters( &deviceCreationParameters); if ( FAILED( pDevice9->CreateVertexBuffer( sizeof( Vertex) * 7954, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &g_pVertexBuffer, 0))) MessageBox( 0, "Failed to create Vertex Buffer.", 0, 0); if ( FAILED( pDevice9->CreateVertexDeclaration( g_vertexElements, &g_pVertexDecl))) MessageBox( 0, "Failed to create Vertex Declaration.", 0, 0); Objects::onCreateDevice( pDevice9); }
Здесь рисую:
STDMETHODIMP CDirect3DDevice8::DrawIndexedPrimitive(THIS_ D3DPRIMITIVETYPE Type, UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) { InitObjects( pDevice9, g_pStreamData9, g_pIndexData9, startIndex, NumVertices, primCount, g_baseVertexIndex); pDevice9->SetVertexDeclaration( g_pVertexDecl); pDevice9->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof( Vertex)); HRESULT hr = Objects::Render( pDevice9, Type, g_baseVertexIndex, minIndex, startIndex, g_Stride, NumVertices, primCount); if ( SUCCEEDED( hr)) return hr; return D3D_OK; }
Тема в архиве.
Тема закрыта.