#include ".\clothsimulation.h" #include "dxutil.h" #include const DWORD CClothSimulation::ClothVertex::FVF = D3DFVF_XYZ|D3DFVF_TEX1; CClothSimulation::CClothSimulation(void) : m_vWindDirection(D3DXVECTOR3(0.0f,0.0f,0.0f)), m_iWindForce(0), m_iNumRow(0), m_iNumCol(0), m_pVB(NULL), m_pIB(NULL), m_pTexture(NULL), m_vVirtualSimulation(D3DXVECTOR3(0,0,0)), m_vMoveParticle(D3DXVECTOR3(0.0f, 0.0f, 0.0f)), m_fRotateParticle(0.0f), m_vWorldPos(D3DXVECTOR3(0,0,0)), m_vMoveValue(D3DXVECTOR3(0,0,0)) { } CClothSimulation::~CClothSimulation(void) { SAFE_RELEASE( m_pVB ); SAFE_RELEASE( m_pIB ); SAFE_RELEASE( m_pTexture ); } void CClothSimulation::Create( LPDIRECT3DDEVICE8 pd3dDevice, int iNumRow, int iNumCol, int iWidth, int iHeight ) { assert( iNumRow > 0 ); assert( iNumCol > 0 ); assert( iWidth > 0 ); assert( iHeight > 0 ); assert( pd3dDevice ); m_pd3dDevice = pd3dDevice; m_iNumRow = iNumRow; m_iNumCol = iNumCol; m_iWidth = iWidth; m_iHeight = iHeight; m_CollisionBox.Init( D3DXVECTOR3(0.0F, 0.0F, 40.0F), D3DXVECTOR3(0.0F, 0.0F, -1.0F), 100, 500, 500, 50 ); D3DXVec3Normalize( &m_CollisionBox.vCollisionNormal, &m_CollisionBox.vCollisionNormal ); m_CollisionBox.vCollisionNormal *= m_CollisionBox.fCollisionConstant; int r, c; float f; D3DXVECTOR3 vL; int count = 0; int n = NUMSTRUCTURALSPRINGS; int iVertexIndex = 0; for( r = 0; r <= NUMROWS; r++ ) { for( c = 0; c <= NUMCOLUMNS; c++ ) { //ÆÄƼŬ ¼¼ÆÃ if((r == 0) && (c == 0)) f = 1; else if((r == NUMROWS) && (c == 0)) f = 2; else if((r == 0) && (c == NUMCOLUMNS)) f = 2; else if((r == NUMROWS) && (c == NUMCOLUMNS)) f = 1; else if(((r == 0) || (r == NUMROWS)) && ((c != 0) && (c != NUMCOLUMNS))) f = 3; else f = 6; m_Particles[r][c].fMass = (f * MASSPERFACE) / 3; m_Particles[r][c].fInvMass = 1 / m_Particles[r][c].fMass; m_Particles[r][c].vPos.x = c * CSTEP - (float)CLOTHWIDTH/2; m_Particles[r][c].vPos.y = (CLOTHHEIGHT - (r * RSTEP)) - (float)CLOTHHEIGHT/2; m_Particles[r][c].vPos.z = 0.0f; m_Particles[r][c].vVel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); m_Particles[r][c].vAccel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); m_Particles[r][c].vForce = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); m_Particles[r][c].bLocked = false; } } for( r = 0; r <= NUMROWS; r++ ) { for( c = 0; c <= NUMCOLUMNS; c++ ) { //¹öÅØ½º¼¼ÆÃ m_ClothVertex[iVertexIndex].pos = m_Particles[r][c].vPos; if( c == 0 ) m_ClothVertex[iVertexIndex].u = 0.0f; else m_ClothVertex[iVertexIndex].u = (float)c/(float)NUMCOLUMNS; if( r == 0 ) m_ClothVertex[iVertexIndex].v = 0.0f; else m_ClothVertex[iVertexIndex].v = (float)r/(float)NUMROWS; iVertexIndex++; //½ºÇÁ¸µ¼¼ÆÃ if(c0 && rCreateVertexBuffer( sizeof(ClothVertex)*NUMVERTICES, D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, ClothVertex::FVF, D3DPOOL_DEFAULT, &m_pVB ); m_pd3dDevice->CreateIndexBuffer( sizeof(WORD)*NUMROWS*NUMCOLUMNS*2*3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIB ); void* pVert; m_pVB->Lock( 0, 0, (BYTE**)&pVert, 0 ); memcpy( pVert, m_ClothVertex, sizeof(ClothVertex)*NUMVERTICES ); m_pVB->Unlock(); void* pIndics; m_pIB->Lock( 0, 0, (BYTE**)&pIndics, 0 ); memcpy( pIndics, m_ClothIndex, sizeof(WORD)*NUMROWS*NUMCOLUMNS*2*3 ); m_pIB->Unlock(); D3DXCreateTextureFromFile( m_pd3dDevice, "c:\\picture.jpg", &m_pTexture ); } void CClothSimulation::Render() { //D3DXMATRIX matWorld; //D3DXMatrixIdentity( &matWorld ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); m_pd3dDevice->SetTexture( 0, m_pTexture ); //m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); //m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); m_pd3dDevice->SetVertexShader( ClothVertex::FVF ); m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(ClothVertex) ); m_pd3dDevice->SetIndices( m_pIB, 0 ); m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, NUMVERTICES, 0, NUMROWS*NUMCOLUMNS*2 ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); } void CClothSimulation::Update( float dt ) { CalculateForce(); Integrate( dt ); void* pVert; m_pVB->Lock( 0, 0, (BYTE**)&pVert, D3DLOCK_DISCARD|D3DLOCK_NOSYSLOCK ); memcpy( pVert, m_ClothVertex, sizeof(ClothVertex)*NUMVERTICES ); m_pVB->Unlock(); } void CClothSimulation::CalculateForce() { int r, c, i, r1, c1, r2, c2; D3DXVECTOR3 dragVector; D3DXVECTOR3 f1, f2, d, v; float L, tempValue; D3DXVECTOR3 vRandWind; for(r=0; r<=NUMROWS; r++) { for(c=0; c<=NUMCOLUMNS; c++) { m_Particles[r][c].vForce = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); //gravity m_Particles[r][c].vForce.y += (float) (GRAVITY * m_Particles[r][c].fMass); // viscous drag dragVector = -m_Particles[r][c].vVel; D3DXVec3Normalize( &dragVector, &dragVector ); float tempValue = D3DXVec3Length( &m_Particles[r][c].vVel ); m_Particles[r][c].vForce += dragVector * tempValue * tempValue * DRAGCOEFFICIENT; // wind if( m_iWindForce ) { vRandWind = D3DXVECTOR3( RandNum((int)m_vWindDirection.x), RandNum((int)m_vWindDirection.y), RandNum((int)m_vWindDirection.z) ); D3DXVec3Normalize( &vRandWind, &vRandWind ); m_Particles[r][c].vForce += vRandWind * (rand()%m_iWindForce); } //virtual simulation m_Particles[r][c].vForce += m_vVirtualSimulation * 10 * (rand()%5+5); if( !m_Particles[r][c].bLocked ) { m_Particles[r][c].vPos += m_vMoveValue*0.8; } } } m_vMoveValue = D3DXVECTOR3(0,0,0); // Process spring forces for(i = 0; i m_CollisionBox.vMin.x && m_Particles[r][c].vPos.y > m_CollisionBox.vMin.y && m_Particles[r][c].vPos.z > m_CollisionBox.vMin.z && m_Particles[r][c].vPos.x < m_CollisionBox.vMax.x && m_Particles[r][c].vPos.y < m_CollisionBox.vMax.y && m_Particles[r][c].vPos.z < m_CollisionBox.vMax.z ) { //Ãæµ¹ °è»ê½ÄÀ» ÇÇÇϱâÀ§ÇÑ ²Ç¼ö m_Particles[r][c].vVel += m_CollisionBox.vCollisionNormal*0.2f; }*/ } //¹öÅØ½º¼¼ÆÃ //¹öö½Ã¹Ä·¹À̼ǹæ½Ä /* m_ClothVertex[iVertexIndex].pos = m_Particles[r][c].vPos - m_vMoveParticle; D3DXMATRIX matRot; D3DXMatrixRotationY( &matRot, -m_fRotateParticle ); D3DXVec3TransformCoord( &m_ClothVertex[iVertexIndex].pos, &m_ClothVertex[iVertexIndex].pos, &matRot ); if( r == 0 && c == 0 ) m_ClothVertex[iVertexIndex].pos = m_vSavePoint2; if( r == 0 && c == 4 ) m_ClothVertex[iVertexIndex].pos = m_vSavePoint; iVertexIndex ++; */ //¸®¾ó½Ã¹Ä·¹À̼ǹæ½Ä m_ClothVertex[iVertexIndex].pos = m_Particles[r][c].vPos; iVertexIndex ++; } } } void CClothSimulation::LockParticle( int iRow, int iCol ) { m_Particles[iRow][iCol].bLocked = true; ParticleRef ref; ref.r = iRow; ref.c = iCol; m_LockedParticleMap.insert( PARTICLEMAP::iterator::value_type(&m_Particles[iRow][iCol], ref) ); } void CClothSimulation::UnLockParticle( int iRow, int iCol ) { PARTICLEMAP::iterator iter; m_Particles[iRow][iCol].bLocked = false; iter = m_LockedParticleMap.find( &m_Particles[iRow][iCol] ); if( iter != m_LockedParticleMap.end() ) { m_LockedParticleMap.erase( iter ); } } void CClothSimulation::MoveLockedParticle( const D3DXVECTOR3& vMoveValue ) { D3DXVECTOR3 TempValue = vMoveValue; D3DXMATRIX matRot; D3DXMatrixRotationY( &matRot, m_fRotateParticle ); D3DXVec3TransformCoord( &TempValue, &TempValue, &matRot ); PARTICLEMAP::iterator iter; for( iter = m_LockedParticleMap.begin(); iter != m_LockedParticleMap.end(); iter++ ) { m_Particles[iter->second.r][iter->second.c].vPos += TempValue; } m_vMoveParticle += TempValue; m_vMoveValue = TempValue; //Ãæµ¹¹Ú½ºÀ̵¿ m_CollisionBox.vCenter += vMoveValue; m_CollisionBox.vMin += vMoveValue; m_CollisionBox.vMax += vMoveValue; } void CClothSimulation::RotateLockedParticle( const D3DXVECTOR3& vRot, int CenterRow, int CenterCol ) { D3DXMATRIX matWorld, matRot, matTrans; D3DXMatrixRotationYawPitchRoll( &matRot, vRot.y, vRot.x, vRot.z ); D3DXVECTOR3 vTemp; D3DXVECTOR3 vPos; m_fRotateParticle += vRot.y; PARTICLEMAP::iterator iter; for( iter = m_LockedParticleMap.begin(); iter != m_LockedParticleMap.end(); iter++ ) { if( iter->second.r == CenterRow && iter->second.c == CenterCol ) continue; vTemp = m_Particles[iter->second.r][iter->second.c].vPos - m_Particles[CenterRow][CenterCol].vPos; D3DXMatrixTranslation( &matTrans, vTemp.x, vTemp.y, vTemp.z ); D3DXMatrixMultiply( &matWorld, &matTrans, &matRot ); vPos = D3DXVECTOR3(0.0F, 0.0F, 0.0F); D3DXVec3TransformCoord( &vPos, &vPos, &matWorld ); m_Particles[iter->second.r][iter->second.c].vPos += vPos - vTemp; } //Ãæµ¹¹Ú½ºÈ¸Àü /* vTemp = m_CollisionBox.vMin - m_Particles[CenterRow][CenterCol].vPos; D3DXMatrixTranslation( &matTrans, vTemp.x, vTemp.y, vTemp.z ); D3DXMatrixMultiply( &matWorld, &matTrans, &matRot ); vPos = D3DXVECTOR3(0.0F, 0.0F, 0.0F); D3DXVec3TransformCoord( &vPos, &vPos, &matWorld ); m_CollisionBox.vMin += vPos - vTemp; vTemp = m_CollisionBox.vMax - m_Particles[CenterRow][CenterCol].vPos; D3DXMatrixTranslation( &matTrans, vTemp.x, vTemp.y, vTemp.z ); D3DXMatrixMultiply( &matWorld, &matTrans, &matRot ); vPos = D3DXVECTOR3(0.0F, 0.0F, 0.0F); D3DXVec3TransformCoord( &vPos, &vPos, &matWorld ); m_CollisionBox.vMax += vPos - vTemp; //Ãæµ¹¹ý¼±È¸Àü D3DXVec3TransformCoord( &m_CollisionBox.vCollisionNormal, &m_CollisionBox.vCollisionNormal, &matRot ); D3DXVec3Normalize( &m_CollisionBox.vCollisionNormal, &m_CollisionBox.vCollisionNormal ); m_CollisionBox.vCollisionNormal *= m_CollisionBox.fCollisionConstant; */ } void CClothSimulation::SetWindFactor( const D3DXVECTOR3& vDirection, int iForce ) { m_vWindDirection = vDirection; m_iWindForce = iForce; } void CClothSimulation::AddCollisionPlane( const D3DXPLANE& Plane ) { } void CClothSimulation::VirtualSimulation( DWORD dwType ) { float fStep = 0.8f; switch( dwType ) { case NOTHING: m_vVirtualSimulation = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); break; case MOVE_FRONT: //m_vVirtualSimulation += D3DXVECTOR3( 0.0f, 0.0f, 0.1f ); //MoveLockedParticle( D3DXVECTOR3(0.0f, sinf(float(GetTickCount()))*1.5f, 0.0f) ); MoveLockedParticle( D3DXVECTOR3(0.0f, 0.0f, -fStep) ); break; case MOVE_BACK: //m_vVirtualSimulation += D3DXVECTOR3( 0.0f, 0.0f, -0.1f ); //MoveLockedParticle( D3DXVECTOR3(0.0f, sinf(float(GetTickCount()))*1.5f, 0.0f) ); MoveLockedParticle( D3DXVECTOR3(0.0f, 0.0f, fStep) ); break; case MOVE_RIGHT: //m_vVirtualSimulation += D3DXVECTOR3( 0.1f, 0.0f, 0.0f ); //MoveLockedParticle( D3DXVECTOR3(0.0f, sinf(float(GetTickCount()))*1.5f, 0.0f) ); MoveLockedParticle( D3DXVECTOR3(-fStep, 0.0f, 0.0f) ); break; case MOVE_LEFT: //m_vVirtualSimulation += D3DXVECTOR3( -0.1f, 0.0f, 0.0f ); //MoveLockedParticle( D3DXVECTOR3(0.0f, sinf(float(GetTickCount()))*1.5f, 0.0f) ); MoveLockedParticle( D3DXVECTOR3(fStep, 0.0f, 0.0f) ); break; case ROTATE_RIGHT: RotateLockedParticle( D3DXVECTOR3(0.0f, 0.05f, 0.0f), 0, 2 ); break; case ROTATE_LEFT: RotateLockedParticle( D3DXVECTOR3(0.0f, -0.05f, 0.0f), 0, 2 ); break; default: break; } if( m_vVirtualSimulation.x > 2.0f ) m_vVirtualSimulation.x = 2.0f; if( m_vVirtualSimulation.x < -2.0f ) m_vVirtualSimulation.x = -2.0f; if( m_vVirtualSimulation.y > 1.0f ) m_vVirtualSimulation.y = 1.0f; if( m_vVirtualSimulation.y < -1.0f ) m_vVirtualSimulation.y = -1.0f; if( m_vVirtualSimulation.z > 1.0f ) m_vVirtualSimulation.z = 1.0f; if( m_vVirtualSimulation.z < -0.5f ) m_vVirtualSimulation.z = -0.5f; } int CClothSimulation::RandNum( int number ) { int rnd=1; if( number < 0 ) { rnd = -number; if( rnd == 0 ) rnd = 1; rnd = -rand()%rnd; } else { if( rnd == 0 ) rnd = 1; rnd = rand()%rnd; } return rnd; } void CClothSimulation::SetPosLockParticle( int iRow, int iCol, const D3DXVECTOR3& vPos ) { // if( m_Particles[iRow][iCol].bLocked ) { //m_Particles[iRow][iCol].vPos = vPos; if( iRow == 0 && iCol == 0 ) m_vSavePoint = vPos; if( iRow == 0 && iCol == 4 ) m_vSavePoint2 = vPos; } } void CClothSimulation::SetWorldPos( const D3DXVECTOR3& vPos ) { m_vWorldPos = vPos; for( int r = 0; r <= NUMROWS; r++ ) { for( int c = 0; c <= NUMCOLUMNS; c++ ) { if( !m_Particles[r][c].bLocked ) m_Particles[r][c].vPos += m_vWorldPos; } } }