int luaGetH(lua_State *L) { float x=(float)lua_tonumber(L, 1); float z=(float)lua_tonumber(L, 2); BOOL hit; FLOAT dist; LPDIRECT3DVERTEXBUFFER8 pVB; LPDIRECT3DINDEXBUFFER8 pIB; WORD* pIndices; D3DVERTEX* pVertices; if(m_pLandMesh==NULL) { lua_pushnumber(L,-100000.0f); return 1; } m_pLandMesh->GetSysMemMesh()->GetVertexBuffer( &pVB ); m_pLandMesh->GetSysMemMesh()->GetIndexBuffer( &pIB ); pIB->Lock( 0, 0, (BYTE**)&pIndices, 0 ); pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ); D3DXVECTOR3 v1,v2; GVector dir2=GVector(0,-1,0); v1.x=x;v1.y=100000.0f;v1.z=z; v2.x=0;v2.y=-1;v2.z=0; D3DXIntersect(m_pLandMesh->GetSysMemMesh(),&v1,&v2,&hit,NULL,NULL,NULL,&dist,NULL,NULL); if(!hit) dist=-100000.0f; else dist=100000.0f-dist; lua_pushnumber(L,dist); return 1; }
//----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Creates the scene geometry //----------------------------------------------------------------------------- HRESULT InitGeometry() { // Create the vertex buffer. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB ) ) ) { return E_FAIL; } // Fill the vertex buffer. We are algorithmically generating a cylinder // here, including the normals, which are used for lighting. CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ) ) ) return E_FAIL; for( DWORD i=0; i<50; i++ ) { FLOAT theta = (2*D3DX_PI*i)/(50-1); pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) ); pVertices[2*i+0].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) ); pVertices[2*i+1].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); } g_pVB->Unlock(); return S_OK; }
//----------------------------------------------------------------------------- // Name: RenderGradientBackground() // Desc: Draws a gradient filled background //----------------------------------------------------------------------------- HRESULT CXBApplication::RenderGradientBackground( DWORD dwTopColor, DWORD dwBottomColor ) { // First time around, allocate a vertex buffer static LPDIRECT3DVERTEXBUFFER8 g_pVB = NULL; if( g_pVB == NULL ) { m_pd3dDevice->CreateVertexBuffer( 4*5*sizeof(FLOAT), D3DUSAGE_WRITEONLY, 0L, D3DPOOL_DEFAULT, &g_pVB ); struct BACKGROUNDVERTEX { D3DXVECTOR4 p; D3DCOLOR color; }; BACKGROUNDVERTEX* v; g_pVB->Lock( 0, 0, (BYTE**)&v, 0L ); v[0].p = D3DXVECTOR4( 0 - 0.5f, 0 - 0.5f, 1.0f, 1.0f ); v[0].color = dwTopColor; v[1].p = D3DXVECTOR4( 640 - 0.5f, 0 - 0.5f, 1.0f, 1.0f ); v[1].color = dwTopColor; v[2].p = D3DXVECTOR4( 0 - 0.5f, 480 - 0.5f, 1.0f, 1.0f ); v[2].color = dwBottomColor; v[3].p = D3DXVECTOR4( 640 - 0.5f, 480 - 0.5f, 1.0f, 1.0f ); v[3].color = dwBottomColor; g_pVB->Unlock(); } // Set states m_pd3dDevice->SetTexture( 0, NULL ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DISABLE ); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); m_pd3dDevice->SetVertexShader( D3DFVF_XYZRHW|D3DFVF_DIFFUSE ); m_pd3dDevice->SetStreamSource( 0, g_pVB, 5*sizeof(FLOAT) ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); // Clear the zbuffer m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0x00000000, 1.0f, 0L ); return S_OK; }
//----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Creates the scene geometry //----------------------------------------------------------------------------- HRESULT InitGeometry() { // Initialize three vertices for rendering a triangle CUSTOMVERTEX g_Vertices[] = { { -1.0f,-1.0f, 0.0f, 0xffff0000, }, { 1.0f,-1.0f, 0.0f, 0xff0000ff, }, { 0.0f, 1.0f, 0.0f, 0xffffffff, }, }; // Create the vertex buffer. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB ) ) ) { return E_FAIL; } // Fill the vertex buffer. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, g_Vertices, sizeof(g_Vertices) ); g_pVB->Unlock(); return S_OK; }
//----------------------------------------------------------------------------- // Name: ApplyEnvironmentMap() // Desc: Performs a calculation on each of the vertices' normals to determine // what the texture coordinates should be for the environment map (in this // case the bump map). //----------------------------------------------------------------------------- VOID CMyD3DApplication::ApplyEnvironmentMap() { EMBOSSVERTEX* pv; DWORD dwNumVertices; dwNumVertices = m_pObject->GetLocalMesh()->GetNumVertices(); LPDIRECT3DVERTEXBUFFER8 pVB; m_pObject->GetLocalMesh()->GetVertexBuffer( &pVB ); pVB->Lock( 0, 0, (BYTE**)&pv, 0 ); // Get the World matrix D3DXMATRIX WV,InvWV; m_pd3dDevice->GetTransform( D3DTS_WORLD, &WV ); D3DXMatrixInverse( &InvWV, NULL, &WV ); // Get the current light position in object space D3DXVECTOR4 vTransformed; D3DXVec3Transform( &vTransformed, (D3DXVECTOR3*)&m_Light.Position, &InvWV ); m_vBumpLightPos.x = vTransformed.x; m_vBumpLightPos.y = vTransformed.y; m_vBumpLightPos.z = vTransformed.z; // Dimensions of texture needed for shifting tex coords D3DSURFACE_DESC d3dsd; m_pEmbossTexture->GetLevelDesc( 0, &d3dsd ); // Loop through the vertices, transforming each one and calculating // the correct texture coordinates. for( WORD i = 0; i < dwNumVertices; i++ ) { // Find light vector in tangent space D3DXVECTOR3 vLightToVertex; D3DXVec3Normalize( &vLightToVertex, &(m_vBumpLightPos - pv[i].p) ); // Create rotation matrix (rotate into tangent space) FLOAT r = D3DXVec3Dot( &vLightToVertex, &pv[i].n ); if( r < 0.f ) { // Don't shift coordinates when light below surface pv[i].tu2 = pv[i].tu; pv[i].tv2 = pv[i].tv; } else { // Shift coordinates for the emboss effect D3DXVECTOR2 vEmbossShift; vEmbossShift.x = D3DXVec3Dot( &vLightToVertex, &m_pTangents[i] ); vEmbossShift.y = D3DXVec3Dot( &vLightToVertex, &m_pBinormals[i] ); D3DXVec2Normalize( &vEmbossShift, &vEmbossShift ); pv[i].tu2 = pv[i].tu + vEmbossShift.x/d3dsd.Width; pv[i].tv2 = pv[i].tv - vEmbossShift.y/d3dsd.Height; } } pVB->Unlock(); pVB->Release(); }
//----------------------------------------------------------------------------- // Name: // Desc: //----------------------------------------------------------------------------- VOID CMyD3DApplication::ComputeTangentsAndBinormals() { EMBOSSVERTEX* pVertices; WORD* pIndices; DWORD dwNumVertices; DWORD dwNumIndices; // Gain access to the object's vertex and index buffers LPDIRECT3DVERTEXBUFFER8 pVB; m_pObject->GetSysMemMesh()->GetVertexBuffer( &pVB ); pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ); dwNumVertices = m_pObject->GetSysMemMesh()->GetNumVertices(); LPDIRECT3DINDEXBUFFER8 pIB; m_pObject->GetSysMemMesh()->GetIndexBuffer( &pIB ); pIB->Lock( 0, 0, (BYTE**)&pIndices, 0 ); dwNumIndices = m_pObject->GetSysMemMesh()->GetNumFaces() * 3; // Allocate space for the vertices' tangents and binormals m_pTangents = new D3DXVECTOR3[dwNumVertices]; m_pBinormals = new D3DXVECTOR3[dwNumVertices]; ZeroMemory( m_pTangents, sizeof(D3DXVECTOR3)*dwNumVertices ); ZeroMemory( m_pBinormals, sizeof(D3DXVECTOR3)*dwNumVertices ); // Generate the vertices' tangents and binormals for( DWORD i=0; i<dwNumIndices; i+=3 ) { WORD a = pIndices[i+0]; WORD b = pIndices[i+1]; WORD c = pIndices[i+2]; // To find a tangent that heads in the direction of +tv(texcoords), // find the components of both vectors on the tangent surface , // and add a linear combination of the two projections that head in the +tv direction m_pTangents[a] += ComputeTangentVector( pVertices[a], pVertices[b], pVertices[c] ); m_pTangents[b] += ComputeTangentVector( pVertices[b], pVertices[a], pVertices[c] ); m_pTangents[c] += ComputeTangentVector( pVertices[c], pVertices[a], pVertices[b] ); } for( i=0; i<dwNumVertices; i++ ) { // Normalize the tangents D3DXVec3Normalize( &m_pTangents[i], &m_pTangents[i] ); // Compute the binormals D3DXVec3Cross( &m_pBinormals[i], &pVertices[i].n, &m_pTangents[i] ); } // Unlock and release the vertex and index buffers pIB->Unlock(); pVB->Unlock(); pIB->Release(); pVB->Release(); }
// Draws a rectangle on screen void D3D_DrawRect ( float x, float y, float width, float height, D3DCOLOR Color ) { d3dvertex_t *rectVert; if (!m_pVertexBuffer) return; m_pVertexBuffer->Lock ( 0, 0, (BYTE**)&rectVert, 0 ); rectVert[0].x = x; rectVert[0].y = y+height; rectVert[0].z = 0; rectVert[0].rwh = 1; rectVert[0].color = Color; rectVert[1].x = x+width; rectVert[1].y = y+height; rectVert[1].z = 0; rectVert[1].rwh = 1; rectVert[1].color = Color; rectVert[2].x = x+width; rectVert[2].y = y; rectVert[2].z = 0; rectVert[2].rwh = 1; rectVert[2].color = Color; rectVert[3].x = x; rectVert[3].y = y; rectVert[3].z = 0; rectVert[3].rwh = 1; rectVert[3].color = Color; /*rectVert[4].x = x+width; rectVert[4].y = y; rectVert[4].z = 0; rectVert[4].rwh = 1; rectVert[4].color = Color; rectVert[5].x = x; rectVert[5].y = y+height; rectVert[5].z = 0; rectVert[5].rwh = 1; rectVert[5].color = Color;*/ m_pVertexBuffer->Unlock ( ); m_pOrigDDevice->SetTexture ( 0, NULL ); m_pOrigDDevice->SetStreamSource ( 0, m_pVertexBuffer, sizeof(d3dvertex_t) ); m_pOrigDDevice->SetVertexShader ( D3D_VERTEX ); if (m_pOrigDDevice->DrawPrimitive ( D3DPT_TRIANGLEFAN, 0, 2 ) != D3D_OK) { assert ( 0 ); } }
//----------------------------------------------------------------------------- // Name: RestoreDeviceObjects() // Desc: Initialize scene objects //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::RestoreDeviceObjects() { m_pFont->RestoreDeviceObjects(); // Set the transform matrices D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -2001.0f ); D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMATRIX matWorld, matView, matProj; D3DXMatrixIdentity( &matWorld ); D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 3000.0f ); m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); // Set any appropiate state m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP ); m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP ); m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_NONE ); // Size the background image BACKGROUNDVERTEX* vBackground; m_pBackgroundVB->Lock( 0, 0, (BYTE**)&vBackground, 0 ); for( UINT i=0; i<4; i ++ ) { vBackground[i].p = D3DXVECTOR4( 0.0f, 0.0f, 0.9f, 1.0f ); vBackground[i].color = 0xffffffff; } vBackground[0].p.y = (FLOAT)m_d3dsdBackBuffer.Height; vBackground[2].p.y = (FLOAT)m_d3dsdBackBuffer.Height; vBackground[2].p.x = (FLOAT)m_d3dsdBackBuffer.Width; vBackground[3].p.x = (FLOAT)m_d3dsdBackBuffer.Width; vBackground[0].tu = 0.0f; vBackground[0].tv = 1.0f; vBackground[1].tu = 0.0f; vBackground[1].tv = 0.0f; vBackground[2].tu = 1.0f; vBackground[2].tv = 1.0f; vBackground[3].tu = 1.0f; vBackground[3].tv = 0.0f; m_pBackgroundVB->Unlock(); return S_OK; }
//----------------------------------------------------------------------------- // Name: Cleanup() // Desc: Releases all previously initialized objects //----------------------------------------------------------------------------- VOID Cleanup() { if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); }
//----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: Initialize scene objects //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InitDeviceObjects() { m_pFont->InitDeviceObjects( m_pd3dDevice ); // Load the texture for the background image if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("Lake.bmp"), &m_pBackgroundTexture ) ) ) return E_FAIL; // Create the bump map texture if( FAILED( CreateBumpMap( 256, 256 ) ) ) return E_FAIL; // Create a square for rendering the background if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(BACKGROUNDVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_BACKGROUNDVERTEX, D3DPOOL_MANAGED, &m_pBackgroundVB ) ) ) return E_FAIL; // Create a square for rendering the lens if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(BUMPVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_BUMPVERTEX, D3DPOOL_MANAGED, &m_pLensVB ) ) ) return E_FAIL; BUMPVERTEX* vLens; m_pLensVB->Lock( 0, 0, (BYTE**)&vLens, 0 ); vLens[0].p = D3DXVECTOR3(-256.0f,-256.0f, 0.0f ); vLens[1].p = D3DXVECTOR3(-256.0f, 256.0f, 0.0f ); vLens[2].p = D3DXVECTOR3( 256.0f,-256.0f, 0.0f ); vLens[3].p = D3DXVECTOR3( 256.0f, 256.0f, 0.0f ); vLens[0].tu1 = 0.0f; vLens[0].tv1 = 1.0f; vLens[1].tu1 = 0.0f; vLens[1].tv1 = 0.0f; vLens[2].tu1 = 1.0f; vLens[2].tv1 = 1.0f; vLens[3].tu1 = 1.0f; vLens[3].tv1 = 0.0f; m_pLensVB->Unlock(); m_bDeviceValidationFailed = FALSE; return S_OK; }
//----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Create the textures and vertex buffers //----------------------------------------------------------------------------- HRESULT InitGeometry() { // Use D3DX to create a texture from a file based image if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "banana.bmp", &g_pTexture ) ) ) return E_FAIL; // Create the vertex buffer. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB ) ) ) { return E_FAIL; } // Fill the vertex buffer. We are setting the tu and tv texture // coordinates, which range from 0.0 to 1.0 CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ) ) ) return E_FAIL; for( DWORD i=0; i<50; i++ ) { FLOAT theta = (2*D3DX_PI*i)/(50-1); pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) ); pVertices[2*i+0].color = 0xffffffff; pVertices[2*i+0].tu = ((FLOAT)i)/(50-1); pVertices[2*i+0].tv = 1.0f; pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) ); pVertices[2*i+1].color = 0xff808080; pVertices[2*i+1].tu = ((FLOAT)i)/(50-1); pVertices[2*i+1].tv = 0.0f; } g_pVB->Unlock(); return S_OK; }
// Rendering library invalid handle void D3D_RendInvalid ( IDirect3DDevice8 *pDevice ) { unsigned int n; if ( m_pOrigTarget ) m_pOrigTarget->Release(); // Release the vertex buffer if ( m_pVertexBuffer ) m_pVertexBuffer->Release(); // Release all fonts for ( n=0; n<m_uiNumFonts; n++ ) { m_pFonts[n]->pFont->Release ( ); m_pFonts[n]->pFont=NULL; } }
// Rendering library restore handle void D3D_RendRestore ( IDirect3DDevice8 *pDevice ) { unsigned int n; m_pOrigDDevice->GetRenderTarget ( &m_pOrigTarget ); // Recreate the vertex buffer m_pOrigDDevice->CreateVertexBuffer ( D3D_MAX_VERTICES*sizeof(d3dvertex_t), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3D_VERTEX, D3DPOOL_DEFAULT, &m_pVertexBuffer ); assert ( m_pVertexBuffer != NULL ); m_pVertexBuffer->SetPriority ( D3DPRIO_LOW ); // Recreate all fonts for (n=0; n<m_uiNumFonts; n++) { HFONT hFont=CreateFont ( 100, 0, 0, 0, 0, 1, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH || FF_DONTCARE, m_pFonts[n]->face_name ); D3DXCreateFont ( m_pOrigDDevice, hFont, &m_pFonts[n]->pFont ); assert ( m_pFonts[n]->pFont != NULL ); m_pFonts[n]->hFont=hFont; } }
//----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: This creates all device-dependent managed objects, such as managed // textures and managed vertex buffers. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InitDeviceObjects() { // Initialize the font's internal textures m_pFont->InitDeviceObjects( m_pd3dDevice ); // Create the tree textures for( DWORD i=0; i<NUMTREETEXTURES; i++ ) { if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, g_strTreeTextures[i], &m_pTreeTextures[i] ) ) ) return D3DAPPERR_MEDIANOTFOUND; } // Create a quad for rendering each tree if( FAILED( m_pd3dDevice->CreateVertexBuffer( NUM_TREES*4*sizeof(TREEVERTEX), D3DUSAGE_WRITEONLY, D3DFVF_TREEVERTEX, D3DPOOL_MANAGED, &m_pTreeVB ) ) ) { return E_FAIL; } // Copy tree mesh data into vertexbuffer TREEVERTEX* v; m_pTreeVB->Lock( 0, 0, (BYTE**)&v, 0 ); INT iTree; DWORD dwOffset = 0; for( iTree = 0; iTree < NUM_TREES; iTree++ ) { memcpy( &v[dwOffset], m_Trees[iTree].v, 4*sizeof(TREEVERTEX) ); m_Trees[iTree].dwOffset = dwOffset; dwOffset += 4; } m_pTreeVB->Unlock(); // Load the skybox if( FAILED( m_pSkyBox->Create( m_pd3dDevice, _T("SkyBox2.x") ) ) ) return D3DAPPERR_MEDIANOTFOUND; // Load the terrain if( FAILED( m_pTerrain->Create( m_pd3dDevice, _T("SeaFloor.x") ) ) ) return D3DAPPERR_MEDIANOTFOUND; // Add some "hilliness" to the terrain LPDIRECT3DVERTEXBUFFER8 pVB; if( SUCCEEDED( m_pTerrain->GetSysMemMesh()->GetVertexBuffer( &pVB ) ) ) { struct VERTEX { FLOAT x,y,z,tu,tv; }; VERTEX* pVertices; DWORD dwNumVertices = m_pTerrain->GetSysMemMesh()->GetNumVertices(); pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 ); for( DWORD i=0; i<dwNumVertices; i++ ) pVertices[i].y = HeightField( pVertices[i].x, pVertices[i].z ); pVB->Unlock(); pVB->Release(); } return S_OK; }
void System2::renderFlame() { unsigned int i, j; unsigned int sub_batch; double t, r, dr; static unsigned char xform_distrib[CHOOSE_XFORM_GRAIN]; dr = 0.0f; for (i = 0; i < NXFORMS; i++) dr += xforms[i].density; dr = dr / CHOOSE_XFORM_GRAIN; j = 0; t = xforms[0].density; r = 0.0f; for(i = 0; i < CHOOSE_XFORM_GRAIN; i++) { while (r >= t) { j++; t += xforms[j].density; } xform_distrib[i] = j; r += dr; } DWORD palette[256]; ColorMap tmpcmap; for(i=0; i < 256; i++) { float tc[4]; ColorMap::rgb2hsv(colormap.data[i],tc); tc[0] += hue_rotation*6; ColorMap::hsv2rgb(tc,tmpcmap.data[i]); palette[i]= ((int)(alpha*105))<<24 | ((int)(tmpcmap.data[i][0]*255))<<16 | ((int)(tmpcmap.data[i][1]*255))<<8 | ((int)(tmpcmap.data[i][2]*255)); } dr = radius; BEGIN_DRAW(center[0],center[1],scale); /*------------------------*/ POINTVERTEX* pVertices; DWORD dwNumParticlesToRender = 0; // Set up the vertex buffer to be rendered g_pd3dDevice->SetStreamSource( 0, ifs_vb, sizeof(POINTVERTEX) ); g_pd3dDevice->SetVertexShader( POINTVERTEX_FVF ); m_dwBase += m_dwFlush; if(m_dwBase >= m_dwDiscard) m_dwBase = 0; #define D3DLOCK_DISCARD 0 WRAP(ifs_vb->Lock( m_dwBase * sizeof(POINTVERTEX), m_dwFlush * sizeof(POINTVERTEX), (BYTE**)&pVertices, m_dwBase ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD )); POINTVERTEX* p=pVertices; // printf("p pVertices[m_dwBase]\n"); // printf("debug %d %d ... %d/%d\n",m_dwBase, dwNumParticlesToRender, m_dwFlush, m_dwDiscard); /*------------------------*/ for(sub_batch = 0; sub_batch < point_quantity; sub_batch += SUB_BATCH_SIZE*5) { register float p0 = ((rand() - RAND_MAX/2)/(float)(RAND_MAX/2));//random_uniform11(); register float p1 = ((rand() - RAND_MAX/2)/(float)(RAND_MAX/2));//random_uniform11(); register float p2 = (rand()/(float)RAND_MAX);//random_uniform01(); i = FUSE; do { int fn = xform_distrib[rand() % CHOOSE_XFORM_GRAIN]; float tx, ty, v; p2 = (p2+xforms[fn].color)*0.5f; tx = coef[0][0] * p0 + coef[1][0] * p1 + coef[2][0]; ty = coef[0][1] * p0 + coef[1][1] * p1 + coef[2][1]; p0 = p1 = 0; v = vari[0]; if(v > 0) { // linear p0 += v * tx; p1 += v * ty; } v = vari[1]; if(v > 0) { // sinusoidal float nx, ny; nx = (float)sin(tx); ny = (float)sin(ty); p0 += v * nx; p1 += v * ny; } v = vari[2]; if(v > 0) { // complex float nx, ny; float r2 = 1.0f/(tx * tx + ty * ty + 1e-6f); nx = tx * r2; ny = ty * r2; p0 += v * nx; p1 += v * ny; } v = vari[3]; if(v > 0) { // swirl float r2 = tx * tx + ty * ty; // /k here is fun float c1 = (float)sin(r2); float c2 = (float)cos(r2); float nx = c1 * tx - c2 * ty; float ny = c2 * tx + c1 * ty; p0 += v * nx; p1 += v * ny; } v = vari[4]; if(v > 0) { // horseshoe float a, c1, c2, nx, ny; if(tx < -EPS || tx > EPS || ty < -EPS || ty > EPS) a = (float)atan2(tx, ty); // times k here is fun else a = 0; c1 = (float)sin(a); c2 = (float)cos(a); nx = c1 * tx - c2 * ty; ny = c2 * tx + c1 * ty; p0 += v * nx; p1 += v * ny; } v = vari[5]; if(v > 0) { // spherical float nx, ny; if(tx < -EPS || tx > EPS || ty < -EPS || ty > EPS) nx = (float)atan2(tx, ty) / M_PI; else nx = 0; ny = (float)sqrt(tx * tx + ty * ty) - 1; p0 += v * nx; p1 += v * ny; } v = vari[6]; if(v > 0) { // bent float nx, ny; nx = tx; ny = ty; if(nx < 0) nx *= 2.0f; if(ny < 0) ny *= 0.5f; p0 += v * nx; p1 += v * ny; } } while(--i); i = SUB_BATCH_SIZE; do { int fn = xform_distrib[rand() % CHOOSE_XFORM_GRAIN]; float tx, ty, v; p2 = (p2+xforms[fn].color)*0.5f; tx = coef[0][0] * p0 + coef[1][0] * p1 + coef[2][0]; ty = coef[0][1] * p0 + coef[1][1] * p1 + coef[2][1]; p0 = p1 = 0; v = vari[0]; if(v > 0) { // linear p0 += v * tx; p1 += v * ty; } v = vari[1]; if(v > 0) { // sinusoidal p0 += v * (float)sin(tx); p1 += v * (float)sin(ty); } v = vari[2]; if(v > 0) { // complex float nx, ny; float r2 = 1.0f/(tx * tx + ty * ty + 1e-6f); nx = tx * r2; ny = ty * r2; p0 += v * nx; p1 += v * ny; } v = vari[3]; if(v > 0) { // swirl float r2 = tx * tx + ty * ty; // /k here is fun float c1 = (float)sin(r2); float c2 = (float)cos(r2); float nx = c1 * tx - c2 * ty; float ny = c2 * tx + c1 * ty; p0 += v * nx; p1 += v * ny; } v = vari[4]; if(v > 0) { // horseshoe float a, c1, c2, nx, ny; if(tx < -EPS || tx > EPS || ty < -EPS || ty > EPS) a = (float)atan2(tx, ty); // times k here is fun else a = 0; c1 = (float)sin(a); c2 = (float)cos(a); nx = c1 * tx - c2 * ty; ny = c2 * tx + c1 * ty; p0 += v * nx; p1 += v * ny; } v = vari[5]; if(v > 0) { // spherical float nx, ny; if(tx < -EPS || tx > EPS || ty < -EPS || ty > EPS) nx = (float)atan2(tx, ty) * (1 / M_PI); else nx = 0; ny = (float)sqrt(tx * tx + ty * ty) - 1; p0 += v * nx; p1 += v * ny; } v = vari[6]; if(v > 0) { // bent float nx, ny; nx = tx; ny = ty; if (nx < 0) nx *= 2.0f; if (ny < 0) ny *= 0.5f; p0 += v * nx; p1 += v * ny; } int k = 255&(int)(p2*256.0f); /* if(k < 0) k = 0; else if(k > 255) k = 255; */ /* DRAW_DOT(p0,p1,dr, tmpcmap.data[k][0], tmpcmap.data[k][1], tmpcmap.data[k][2], alpha); */ /* { \ float f[4]; f[0]=p0; f[1]=p1; f[2]=0; *((int*)&f[3])=palette[k]; g_pd3dDevice->DrawPrimitiveUP( D3DPT_POINTLIST, 1, f, 4*4); } */ // printf("\t%d\n", dwNumParticlesToRender); p->v.x=p0; p->v.y=p1; // p->v.z=0; p->color=palette[k]; p++; //dwNumParticlesToRender++; if( ++dwNumParticlesToRender == m_dwFlush ) { // Done filling this chunk of the vertex buffer. Lets unlock and // draw this portion so we can begin filling the next chunk. ifs_vb->Unlock(); // printf("draw %d %d ... %d/%d\n",m_dwBase, dwNumParticlesToRender, m_dwFlush, m_dwDiscard); WRAP(g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, m_dwBase, dwNumParticlesToRender)); // Lock the next chunk of the vertex buffer. If we are at the // end of the vertex buffer, DISCARD the vertex buffer and start // at the beginning. Otherwise, specify NOOVERWRITE, so we can // continue filling the VB while the previous chunk is drawing. m_dwBase += m_dwFlush; if(m_dwBase >= m_dwDiscard) m_dwBase = 0; WRAP(ifs_vb->Lock( m_dwBase * sizeof(POINTVERTEX), m_dwFlush * sizeof(POINTVERTEX), (BYTE**) &pVertices, m_dwBase ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD ) ); // printf("p pVertices[m_dwBase]\n"); p=pVertices; dwNumParticlesToRender = 0; } } while(--i); // printf("---\n"); } END_DRAW(); /*------------------------*/ // printf("enddraw\n"); // Unlock the vertex buffer ifs_vb->Unlock(); // Render any remaining particles if( dwNumParticlesToRender ) { WRAP(g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, m_dwBase, dwNumParticlesToRender )); } // return S_OK; /*------------------------*/ }
BRUSH* ConvertXModelToBrushFormat ( char* szFilename, BRUSH* pBrush, int* piCount, LPDIRECT3DDEVICE8 lpDevice ) { // takes an x model and converts it into brushes // check the pointers are valid if ( !szFilename || !piCount ) return NULL; // used to access vertex data struct sMeshData { float x, y, z; float nx, ny, nz; float tu, tv; }; // variable declarations tagModelData* ptr; // model data LPDIRECT3DVERTEXBUFFER8 pMeshVertexBuffer; // vertex buffer LPDIRECT3DINDEXBUFFER8 pMeshIndexBuffer; // index buffer sMeshData* pMeshVertices; // mesh vertices WORD* pMeshIndices; // mesh indices sMesh* pMesh; // mesh data int iCount; // load the model Constructor ( lpDevice ); ptr = Load ( 1, szFilename ); pMesh = ptr->m_Object.m_Meshes; // count the number of brushes so we can allocate enough memory for them iCount = 0; while ( pMesh ) { pMesh = pMesh->m_Next; iCount++; } // store the number of models in the brush count pointer *piCount = iCount; // now setup the brushes pBrush = new BRUSH [ iCount ]; // allocate memory // set the mesh pointer back to the original mesh pMesh = ptr->m_Object.m_Meshes; // run through all meshes and store the brush data // first off set iCount to 0 so we know which brush // we are dealing with iCount = 0; while ( pMesh ) { int iInd = 0; DWORD dwNumVertices = pMesh->m_Mesh->GetNumVertices ( ); DWORD dwNumFaces = pMesh->m_Mesh->GetNumFaces ( ); pBrush [ iCount ].Faces = new POLYGON [ dwNumFaces ]; pBrush [ iCount ].FaceCount = dwNumFaces; pBrush [ iCount ].Bounds.Max = D3DXVECTOR3 ( 150.0f, 150.0f, 150.0f ); pBrush [ iCount ].Bounds.Min = D3DXVECTOR3 ( -150.0f, -150.0f, -150.0f ); pBrush [ iCount ].BSPTree = NULL; pMesh->m_Mesh->GetVertexBuffer ( &pMeshVertexBuffer ); pMesh->m_Mesh->GetIndexBuffer ( &pMeshIndexBuffer ); DWORD dwFVF = pMesh->m_Mesh->GetFVF ( ); pMeshVertexBuffer->Lock ( 0, pMesh->m_Mesh->GetNumVertices ( ) * sizeof ( sMeshData ), ( BYTE** ) &pMeshVertices, 0 ); pMeshIndexBuffer->Lock ( 0, 3 * pMesh->m_Mesh->GetNumFaces ( ) * sizeof ( WORD ), ( BYTE** ) &pMeshIndices, 0 ); for ( int iTemp = 0; iTemp < dwNumFaces; iTemp++ ) { char szX [ 256 ]; char szY [ 256 ]; char szZ [ 256 ]; int iA = pMeshIndices [ iInd + 0 ]; int iB = pMeshIndices [ iInd + 1 ]; int iC = pMeshIndices [ iInd + 2 ]; WORD wIndices [ ] = { 0, 1, 2 }; pBrush [ iCount ].Faces [ iTemp ].IndexCount = 3; pBrush [ iCount ].Faces [ iTemp ].TextureIndex = 0; pBrush [ iCount ].Faces [ iTemp ].VertexCount = 3; pBrush [ iCount ].Faces [ iTemp ].Indices = new WORD [ 3 ]; pBrush [ iCount ].Faces [ iTemp ].Vertices = new D3DVERTEX [ 3 ]; pBrush [ iCount ].Faces [ iTemp ].Vertices [ 0 ] = SetupVertex ( pMeshVertices [ iA ].x, pMeshVertices [ iA ].y, pMeshVertices [ iA ].z, pMeshVertices [ iA ].tu, pMeshVertices [ iA ].tv ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ 1 ] = SetupVertex ( pMeshVertices [ iB ].x, pMeshVertices [ iB ].y, pMeshVertices [ iB ].z, pMeshVertices [ iB ].tu, pMeshVertices [ iB ].tv ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ 2 ] = SetupVertex ( pMeshVertices [ iC ].x, pMeshVertices [ iC ].y, pMeshVertices [ iC ].z, pMeshVertices [ iC ].tu, pMeshVertices [ iC ].tv ); for ( int iChar = 0; iChar < 3; iChar++ ) { sprintf ( szX, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x ); sprintf ( szY, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y ); sprintf ( szZ, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x = atof ( szX ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y = atof ( szY ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z = atof ( szZ ); } memcpy ( pBrush [ iCount ].Faces [ iTemp ].Indices, wIndices, sizeof ( wIndices ) ); CalculateNormal ( &pBrush [ iCount ].Faces [ iTemp ] ); iInd += 3; } SetBlockPosition ( &pBrush [ iCount ], 0.0f, 0.0f, 0.0f, 1.0f ); pMeshVertexBuffer->Unlock ( ); pMeshIndexBuffer->Unlock ( ); iCount++; pMesh = pMesh->m_Next; } iCount = 0; pMesh = ptr->m_Object.m_Meshes; for ( int iTemp = ptr->m_Object.m_NumFrames; iTemp > 0; iTemp-- ) { sFrame* pFrame = ptr->m_Object.m_Frames->FindFrame ( iTemp ); if ( pFrame ) { pBrush [ iCount ].Matrix._41 = pFrame->m_matOriginal._41; pBrush [ iCount ].Matrix._42 = pFrame->m_matOriginal._42; pBrush [ iCount ].Matrix._43 = pFrame->m_matOriginal._43; iCount++; } } return pBrush; }
Filename_notice *prepare_filename_notice(LPDIRECT3DDEVICE8 pd3dDevice, char const *filename) { HRESULT result; Filename_notice *notice = NULL; HDC hDC = NULL; HFONT hFont = NULL; SIZE size; int width, height; LPDIRECT3DTEXTURE8 pTexture = NULL; LPDIRECT3DVERTEXBUFFER8 pVB = NULL; DWORD *pBitmapBits = NULL; BITMAPINFO bmi; HBITMAP hbmBitmap = NULL; D3DLOCKED_RECT d3dlr; BYTE *pDstRow; int x, y; hDC = CreateCompatibleDC(NULL); SetMapMode(hDC, MM_TEXT); hFont = CreateFont( FONT_HEIGHT, // height 0, // width (0 = closest) 0, // escapement (0 = none) 0, // orientation (0 = none) FW_NORMAL, // bold FALSE, // italic FALSE, // underline FALSE, // strikeout DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, // TrueType (OUT_TT_PRECIS) doesn't help CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, FONT_NAME); if (hFont == NULL) { goto done; } // Set text properties SelectObject(hDC, hFont); SetTextColor(hDC, RGB(255,255,255)); SetBkColor(hDC, 0x00000000); SetTextAlign(hDC, TA_TOP); GetTextExtentPoint32(hDC, filename, strlen(filename), &size); width = size.cx; height = size.cy; // Create a new texture for the font result = pd3dDevice->CreateTexture(width, height, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &pTexture); if (FAILED(result)) { goto done; } // Prepare to create a bitmap ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = -height; // negative means top-down bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 32; hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0); SelectObject(hDC, hbmBitmap); ExtTextOut(hDC, 0, 0, ETO_OPAQUE, NULL, filename, strlen(filename), NULL); // Lock the surface and write the alpha values for the set pixels pTexture->LockRect(0, &d3dlr, 0, 0); pDstRow = (BYTE*)d3dlr.pBits; for (y = 0; y < height; y++) { WORD *pDst16 = (WORD *)pDstRow; for (x = 0; x < width; x++) { BYTE bAlpha = (BYTE)((pBitmapBits[width*y + x] & 0xff) >> 4); if (bAlpha > 0) { *pDst16++ = (WORD)((bAlpha << 12) | 0x0fff); } else { *pDst16++ = (WORD)(0x0000); } } pDstRow += d3dlr.Pitch; } // Done updating texture pTexture->UnlockRect(0); // Create vertices result = pd3dDevice->CreateVertexBuffer(4*sizeof(FONT2DVERTEX), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &pVB); if (FAILED(result)) { goto done; } notice = new Filename_notice; notice->width = width; notice->height = height; notice->pd3dDevice = pd3dDevice; notice->pTexture = pTexture; pTexture = NULL; notice->pVB = pVB; pVB = NULL; pd3dDevice->BeginStateBlock(); apply_render_state(pd3dDevice); pd3dDevice->SetTexture(0, notice->pTexture); pd3dDevice->EndStateBlock(¬ice->dwSavedStateBlock); pd3dDevice->BeginStateBlock(); apply_render_state(pd3dDevice); pd3dDevice->SetTexture(0, notice->pTexture); pd3dDevice->EndStateBlock(¬ice->dwDrawTextStateBlock); done: if (pVB != NULL) { pVB->Release(); } if (pTexture != NULL) { pTexture->Release(); } if (hbmBitmap != NULL) { DeleteObject(hbmBitmap); } if (hFont != NULL) { DeleteObject(hFont); } if (hDC != NULL) { DeleteDC(hDC); } return notice; }
HRESULT CMyD3DApplication::LoadMeshData ( LPD3DXMESH *ppMesh, LPD3DXBUFFER *ppAdjacencyBuffer ) { LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL; LPD3DXBUFFER pD3DXMtrlBuffer = NULL; BYTE* pVertices; TCHAR strMesh[512]; HRESULT hr = S_OK; BOOL bNormalsInFile; LPD3DXMESH pMeshSysMem = NULL; LPD3DXMESH pMeshTemp; DWORD *rgdwAdjacencyTemp = NULL; DWORD i; D3DXMATERIAL* d3dxMaterials; DWORD dw32Bit; // Get a path to the media file DXUtil_FindMediaFile( strMesh, m_strMeshFilename ); // Load the mesh from the specified file hr = D3DXLoadMeshFromX( strMesh, D3DXMESH_SYSTEMMEM, m_pd3dDevice, ppAdjacencyBuffer, &pD3DXMtrlBuffer, &m_dwNumMaterials, &pMeshSysMem ); if( FAILED(hr) ) goto End; // remember if the mesh is 32 or 16 bit, to be added in on the clones dw32Bit = pMeshSysMem->GetOptions() & D3DXMESH_32BIT; // Get the array of materials out of the returned buffer, and allocate a texture array d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials]; m_pMeshTextures = new LPDIRECT3DTEXTURE8[m_dwNumMaterials]; for( i=0; i<m_dwNumMaterials; i++ ) { m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse; m_pMeshTextures[i] = NULL; // Get a path to the texture TCHAR strPath[512]; if (d3dxMaterials[i].pTextureFilename != NULL) { DXUtil_FindMediaFile( strPath, d3dxMaterials[i].pTextureFilename ); // Load the texture D3DXCreateTextureFromFile( m_pd3dDevice, strPath, &m_pMeshTextures[i] ); } } // Done with the material buffer SAFE_RELEASE( pD3DXMtrlBuffer ); // Lock the vertex buffer, to generate a simple bounding sphere hr = pMeshSysMem->GetVertexBuffer( &pMeshVB ); if( SUCCEEDED(hr) ) { hr = pMeshVB->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK ); if( SUCCEEDED(hr) ) { hr = D3DXComputeBoundingSphere( pVertices, pMeshSysMem->GetNumVertices(), pMeshSysMem->GetFVF(), &m_vObjectCenter, &m_fObjectRadius ); pMeshVB->Unlock(); } pMeshVB->Release(); } if( FAILED(hr) ) goto End; // remember if there were normals in the file, before possible clone operation bNormalsInFile = pMeshSysMem->GetFVF() & D3DFVF_NORMAL; // if using 32byte vertices, check fvf if (m_bForce32ByteFVF) { // force 32 byte vertices if (pMeshSysMem->GetFVF() != (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)) { hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, m_pd3dDevice, &pMeshTemp ); if( FAILED(hr) ) goto End; pMeshSysMem->Release(); pMeshSysMem = pMeshTemp; } } // otherwise, just make sure that there is a normal mesh else if ( !(pMeshSysMem->GetFVF() & D3DFVF_NORMAL) ) { hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), pMeshSysMem->GetFVF() | D3DFVF_NORMAL, m_pd3dDevice, &pMeshTemp ); if (FAILED(hr)) return hr; pMeshSysMem->Release(); pMeshSysMem = pMeshTemp; } // Compute normals for the mesh, if not present if (!bNormalsInFile) { D3DXComputeNormals( pMeshSysMem, NULL ); } *ppMesh = pMeshSysMem; pMeshSysMem = NULL; End: SAFE_RELEASE( pMeshSysMem ); return hr; }