void Storm3D_Spotlight::renderStencilCone(Storm3D_Camera &camera) { data->createStencilCone(); D3DXVECTOR3 lightPosition(data->properties.position.x, data->properties.position.y, data->properties.position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(data->properties.direction.x, data->properties.direction.y, data->properties.direction.z); D3DXMATRIX tm; D3DXMatrixLookAtLH(&tm, &lightPosition, &lookAt, &up); /* VC3 cameraDir = camera.GetDirection(); cameraDir.Normalize(); D3DXVECTOR3 direction(cameraDir.x, cameraDir.y, cameraDir.z); D3DXVec3TransformNormal(&direction, &direction, &tm); */ float det = D3DXMatrixDeterminant(&tm); D3DXMatrixInverse(&tm, &det, &tm); Storm3D_ShaderManager::GetSingleton()->SetWorldTransform(data->device, tm, true); data->coneStencilVertexShader->apply(); data->coneStencilVertexBuffer.apply(data->device, 0); data->coneStencilIndexBuffer.render(data->device, CONE_FACES, CONE_VERTICES); }
/** * Use the transform of the camera to create the view matrix used for rendering (by taking its inverse) * This is called within camera functions every time its transform is changed * @author Serge Radinovich */ void Camera::updateViewMatrix() { D3DXMATRIX _worldMtx = *m_transform.matrix(); float _fDeterminant = D3DXMatrixDeterminant(&_worldMtx); D3DXMatrixInverse(&_worldMtx, &_fDeterminant, &_worldMtx); m_viewMtx = _worldMtx; }
void Storm3D_SpotlightShared::setClipPlanes(const float *cameraView) { D3DXMATRIX m(cameraView); float determinant = D3DXMatrixDeterminant(&m); D3DXMatrixInverse(&m, &determinant, &m); D3DXMatrixTranspose(&m, &m); D3DXVECTOR3 d(direction.x, direction.y, direction.z); VC2 bd(d.x, d.z); bd.Normalize(); D3DXVECTOR3 p1(position.x - 8*bd.x, position.y, position.z - 8*bd.y); //D3DXVECTOR3 p1(position.x - 1*bd.x, position.y, position.z - 1*bd.y); D3DXVECTOR3 p2(p1.x, p1.y + 5.f, p1.z); float angle = D3DXToRadian(fov) * .55f; D3DXPLANE leftPlane; D3DXMATRIX leftTransform; D3DXMatrixRotationY(&leftTransform, -angle); D3DXVECTOR3 leftPoint(direction.x, 0, direction.z); D3DXVECTOR4 leftPoint2; D3DXVec3Transform(&leftPoint2, &leftPoint, &leftTransform); leftPoint = p1; leftPoint.x += leftPoint2.x; leftPoint.z += leftPoint2.z; D3DXPlaneFromPoints(&leftPlane, &p1, &p2, &leftPoint); D3DXPlaneNormalize(&leftPlane, &leftPlane); D3DXPlaneTransform(&leftPlane, &leftPlane, &m); D3DXPLANE rightPlane; D3DXMATRIX rightTransform; D3DXMatrixRotationY(&rightTransform, angle); D3DXVECTOR3 rightPoint(direction.x, 0, direction.z); D3DXVECTOR4 rightPoint2; D3DXVec3Transform(&rightPoint2, &rightPoint, &rightTransform); rightPoint = p1; rightPoint.x += rightPoint2.x; rightPoint.z += rightPoint2.z; D3DXPlaneFromPoints(&rightPlane, &rightPoint, &p2, &p1); D3DXPlaneNormalize(&rightPlane, &rightPlane); D3DXPlaneTransform(&rightPlane, &rightPlane, &m); D3DXPLANE backPlane; D3DXVECTOR3 pb(p1.x, p1.y, p1.z); D3DXPlaneFromPointNormal(&backPlane, &pb, &d); D3DXPlaneNormalize(&backPlane, &backPlane); D3DXPlaneTransform(&backPlane, &backPlane, &m); device.SetClipPlane(0, leftPlane); device.SetClipPlane(1, rightPlane); device.SetClipPlane(2, backPlane); device.SetRenderState(D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 | D3DCLIPPLANE1 | D3DCLIPPLANE2); }
void lcNode::AttachChild(lcNode* a_pChild) { //Change Local of Child D3DXMATRIX kInvRotate; float fDeterminant = D3DXMatrixDeterminant(&m_mLocalRotate); D3DXMatrixInverse(&kInvRotate,&fDeterminant,&m_mLocalRotate); a_pChild->m_kLocalTranslate -= m_kLocalTranslate; D3DXVec3TransformCoord(&a_pChild->m_kLocalTranslate,&a_pChild->m_kLocalTranslate,&kInvRotate); D3DXMatrixMultiply(&a_pChild->m_mLocalRotate,&a_pChild->m_mLocalRotate,&kInvRotate); a_pChild->m_pParent = this; m_pChildren.push_back(a_pChild); m_uiChildCount++; }
QUAT Storm3D_Spotlight::getOrientation() const { D3DXVECTOR3 lightPosition(data->properties.position.x, data->properties.position.y, data->properties.position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(data->properties.direction.x, data->properties.direction.y, data->properties.direction.z); D3DXMATRIX tm; D3DXMatrixLookAtLH(&tm, &lightPosition, &lookAt, &up); float det = D3DXMatrixDeterminant(&tm); D3DXMatrixInverse(&tm, &det, &tm); MAT m; for(int j = 0; j < 4; ++j) for(int i = 0; i < 4; ++i) m.Set(j*4 + i, tm[j*4 + i]); return m.GetRotation(); }
Matrix3& Matrix3::Invert() { #ifdef __USE_D3DX__ Float32 fDet; fDet = D3DXMatrixDeterminant( (D3DXMATRIX*)&mat ); D3DXMatrixInverse( (D3DXMATRIX*)&mat, &fDet, (D3DXMATRIX*)&mat ); #else Real inv[16], fDet; inv[0] = e[5] * e[10] * e[15] - e[5] * e[11] * e[14] - e[9] * e[6] * e[15] + e[9] * e[7] * e[14] + e[13] * e[6] * e[11] - e[13] * e[7] * e[10]; inv[4] =-e[4] * e[10] * e[15] + e[4] * e[11] * e[14] + e[8] * e[6] * e[15] - e[8] * e[7] * e[14] - e[12] * e[6] * e[11] + e[12] * e[7] * e[10]; inv[8] = e[4] * e[9] * e[15] - e[4] * e[11] * e[13] - e[8] * e[5] * e[15] + e[8] * e[7] * e[13] + e[12] * e[5] * e[11] - e[12] * e[7] * e[9]; inv[12] =-e[4] * e[9] * e[14] + e[4] * e[10] * e[13] + e[8] * e[5] * e[14] - e[8] * e[6] * e[13] - e[12] * e[5] * e[10] + e[12] * e[6] * e[9]; inv[1] =-e[1] * e[10] * e[15] + e[1] * e[11] * e[14] + e[9] * e[2] * e[15] - e[9] * e[3] * e[14] - e[13] * e[2] * e[11] + e[13] * e[3] * e[10]; inv[5] = e[0] * e[10] * e[15] - e[0] * e[11] * e[14] - e[8] * e[2] * e[15] + e[8] * e[3] * e[14] + e[12] * e[2] * e[11] - e[12] * e[3] * e[10]; inv[9] =-e[0] * e[9] * e[15] + e[0] * e[11] * e[13] + e[8] * e[1] * e[15] - e[8] * e[3] * e[13] - e[12] * e[1] * e[11] + e[12] * e[3] * e[9]; inv[13] = e[0] * e[9] * e[14] - e[0] * e[10] * e[13] - e[8] * e[1] * e[14] + e[8] * e[2] * e[13] + e[12] * e[1] * e[10] - e[12] * e[2] * e[9]; inv[2] = e[1] * e[6] * e[15] - e[1] * e[7] * e[14] - e[5] * e[2] * e[15] + e[5] * e[3] * e[14] + e[13] * e[2] * e[7] - e[13] * e[3] * e[6]; inv[6] =-e[0] * e[6] * e[15] + e[0] * e[7] * e[14] + e[4] * e[2] * e[15] - e[4] * e[3] * e[14] - e[12] * e[2] * e[7] + e[12] * e[3] * e[6]; inv[10] = e[0] * e[5] * e[15] - e[0] * e[7] * e[13] - e[4] * e[1] * e[15] + e[4] * e[3] * e[13] + e[12] * e[1] * e[7] - e[12] * e[3] * e[5]; inv[14] =-e[0] * e[5] * e[14] + e[0] * e[6] * e[13] + e[4] * e[1] * e[14] - e[4] * e[2] * e[13] - e[12] * e[1] * e[6] + e[12] * e[2] * e[5]; inv[3] =-e[1] * e[6] * e[11] + e[1] * e[7] * e[10] + e[5] * e[2] * e[11] - e[5] * e[3] * e[10] - e[9] * e[2] * e[7] + e[9] * e[3] * e[6]; inv[7] = e[0] * e[6] * e[11] - e[0] * e[7] * e[10] - e[4] * e[2] * e[11] + e[4] * e[3] * e[10] + e[8] * e[2] * e[7] - e[8] * e[3] * e[6]; inv[11] =-e[0] * e[5] * e[11] + e[0] * e[7] * e[9] + e[4] * e[1] * e[11] - e[4] * e[3] * e[9] - e[8] * e[1] * e[7] + e[8] * e[3] * e[5]; inv[15] = e[0] * e[5] * e[10] - e[0] * e[6] * e[9] - e[4] * e[1] * e[10] + e[4] * e[2] * e[9] + e[8] * e[1] * e[6] - e[8] * e[2] * e[5]; fDet = e[0] * inv[0] + e[1] * inv[4] + e[2] * inv[8] + e[3] * inv[12]; if( fDet != 0 ) { fDet = 1.0f / fDet; for( Int32 i = 0; i < 16; i++ ) (*this)[i] = inv[i] * fDet; } #endif return *this; }
LRESULT CALLBACK d3d9::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) DestroyWindow(hWnd); break; case WM_LBUTTONDOWN: { Ray ray; if (CalcPickingRay(LOWORD(lParam), HIWORD(lParam), g_pDevice, &ray)) { D3DXMATRIX view; g_pDevice->GetTransform(D3DTS_VIEW, &view); D3DXMATRIX inverse; float determinant = D3DXMatrixDeterminant(&view); D3DXMatrixInverse(&inverse, &determinant, &view); TransformRay(&ray, &inverse); if (RayHitSephere(&ray, &g_BSephere)) { MessageBox(0, "Hit!", "HIT", 0); } } break; } } return DefWindowProc(hWnd, msg, wParam, lParam); }
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize, Storm3D_Scene *scene) { D3DXMATRIX light; D3DXVECTOR3 lightPosition(position.x, position.y, position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z); D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up); // Create frustum vertices D3DXVECTOR3 v[5]; v[0] = D3DXVECTOR3(0, 0, 0); v[1] = D3DXVECTOR3(0, 0, 1.f); v[2] = D3DXVECTOR3(0, 0, 1.f); v[3] = D3DXVECTOR3(0, 0, 1.f); v[4] = D3DXVECTOR3(0, 0, 1.f); float det = D3DXMatrixDeterminant(&light); D3DXMatrixInverse(&light, &det, &light); float angle = D3DXToRadian(fov) * .5f; for(int i = 0; i <= 4; ++i) { if(i > 0) { float z = v[i].z; if(i == 1 || i == 2) { v[i].x = z * sinf(angle); v[i].z = z * cosf(angle); } else { v[i].x = z * sinf(-angle); v[i].z = z * cosf(-angle); } if(i == 1 || i == 3) v[i].y = z * sinf(angle); else v[i].y = z * sinf(-angle); float scale = range / cosf(angle); v[i] *= scale; } D3DXVec3TransformCoord(&v[i], &v[i], &light); } // Create area const Frustum &frustum = camera.getFrustum(); int minX = screenSize.x; int minY = screenSize.y; int maxX = 0; int maxY = 0; for(int i = 0; i < 6; ++i) { VC3 v1; VC3 v2; VC3 v3; if(i == 0) { v1 = toVC3(v[0]); v2 = toVC3(v[1]); v3 = toVC3(v[2]); } else if(i == 1) { v1 = toVC3(v[0]); v2 = toVC3(v[2]); v3 = toVC3(v[4]); } else if(i == 2) { v1 = toVC3(v[0]); v2 = toVC3(v[3]); v3 = toVC3(v[4]); } else if(i == 3) { v1 = toVC3(v[0]); v2 = toVC3(v[1]); v3 = toVC3(v[3]); } else if(i == 4) { v1 = toVC3(v[1]); v2 = toVC3(v[2]); v3 = toVC3(v[3]); } else if(i == 5) { v1 = toVC3(v[4]); v2 = toVC3(v[2]); v3 = toVC3(v[3]); } const ClipPolygon &clipPolygon = clipTriangleToFrustum(v1, v2, v3, frustum); for(int j = 0; j < clipPolygon.vertexAmount; ++j) { VC3 result; float rhw = 0.f; float real_z = 0.f; camera.GetTransformedToScreen(clipPolygon.vertices[j], result, rhw, real_z); int x = int(result.x * screenSize.x); int y = int(result.y * screenSize.y); //if(x < -1 || x > screenSize.x) // continue; //if(y < -1 || x > screenSize.y) // continue; x = max(x, 0); y = max(y, 0); x = min(x, screenSize.x - 1); y = min(y, screenSize.y - 1); maxX = max(x, maxX); maxY = max(y, maxY); minX = min(x, minX); minY = min(y, minY); /* // Visualize clipped polygons if(scene) { VC3 p1 = clipPolygon.vertices[j]; VC3 p2 = clipPolygon.vertices[(j + 1) % clipPolygon.vertexAmount]; for(int k = 0; k < 5; ++k) { const VC3 &planeNormal = frustum.planeNormals[k]; PLANE plane; if(k == 0) plane.MakeFromNormalAndPosition(planeNormal, frustum.position + planeNormal); else plane.MakeFromNormalAndPosition(planeNormal, frustum.position); float d1 = plane.GetPointRange(p1); float d2 = plane.GetPointRange(p2); if(d1 < .25f) p1 += planeNormal * (.25f - d1); if(d2 < .25f) p2 += planeNormal * (.25f - d2); } scene->AddLine(p1, p2, COL(1.f, 1.f, 1.f)); } */ } } RECT rc; bool visible = false; if(maxX > minX && maxY > minY) { visible = true; rc.left = minX; rc.top = minY; rc.right = maxX; rc.bottom = maxY; } else { visible = false; rc.left = 0; rc.top = 0; rc.right = 1; rc.bottom = 1; } /* // Visualize scissor area if(scene && visible) { static DWORD foo = GetTickCount(); int dif = (GetTickCount() - foo) % 2000; if(dif < 1000) scene->Render2D_Picture(0, VC2(float(minX), float(minY)), VC2(float(maxX - minX), float(maxY - minY)), 0.5f, 0.f, 0, 0, 0, 0, false); } */ device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); return visible; }
void Storm3D_SpotlightShared::updateMatrices(const D3DXMATRIX &cameraView, float bias) { D3DXVECTOR3 lightPosition(position.x, position.y, position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z); D3DXMatrixPerspectiveFovLH(&lightProjection, D3DXToRadian(fov), 1.f, .2f, range); D3DXMATRIX cameraMatrix(cameraView); float det = D3DXMatrixDeterminant(&cameraMatrix); D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix); float currentBias = bias; for(int i = 0; i < 2; ++i) { D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up); //if(i == 1) // currentBias = 0; if(i == 1) currentBias = 1.f; // Tweak matrix float soffsetX = 0.5f; float soffsetY = 0.5f; float scale = 0.5f; /* D3DXMATRIX shadowTweak( scale, 0.0f, 0.0f, 0.0f, 0.0f, -scale, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, soffsetX, soffsetY, currentBias, 1.0f ); */ D3DXMATRIX shadowTweak( scale, 0.0f, 0.0f, 0.0f, 0.0f, -scale, 0.0f, 0.0f, 0.0f, 0.0f, currentBias, 0.0f, soffsetX, soffsetY, 0.f, 1.0f ); D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak); D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]); D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection); shaderProjection[i] = shadowProjection[i]; D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]); } { float xf = (1.f / resolutionX * .5f); float yf = (1.f / resolutionY * .5f); float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf; float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf; /* D3DXMATRIX shadowTweak( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, -scaleY, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, sX, sY, bias, 1.0f ); */ D3DXMATRIX shadowTweak( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, -scaleY, 0.0f, 0.0f, 0.0f, 0.0f, bias, 0.0f, sX, sY, 0.f, 1.0f ); D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak); D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection); } }
void Storm3D_SpotlightShared::updateMatricesOffCenter(const D3DXMATRIX &cameraView, const VC2 &min, const VC2 &max, float height, Storm3D_Camera &camera) { // Position of the light in global coordinates // Y-axis is height D3DXVECTOR3 lightPosition(position.x, position.y, position.z); // Up vector (z-axis) D3DXVECTOR3 up(0.f, 0.f, 1.f); // Look direction D3DXVECTOR3 lookAt = lightPosition; lookAt.y -= 1.f; { // max and min define the extents of light area in local coordinates // Z-axis is height float zmin = 0.2f; //float zmax = std::max(range, height) * 1.4f; // height is light height from light properties float zmax = height; float factor = 1.5f * zmin / height; float xmin = min.x * factor; float xmax = max.x * factor; float ymin = min.y * factor; float ymax = max.y * factor; D3DXMatrixPerspectiveOffCenterLH(&lightProjection, xmin, xmax, ymin, ymax, zmin, zmax); // Calculate the extents of light area in global coordinates VC2 worldMin = min; worldMin.x += position.x; worldMin.y += position.z; VC2 worldMax = max; worldMax.x += position.x; worldMax.y += position.z; // Generate approximate camera for culling. // Calculate range of the camera. // Y-axis is height float planeY = position.y - height; // Calculate distances from light position to light plane edges VC3 p1 = VC3( worldMin.x, planeY, worldMin.y ) - position; VC3 p2 = VC3( worldMax.x, planeY, worldMin.y ) - position; VC3 p3 = VC3( worldMax.x, planeY, worldMax.y ) - position; VC3 p4 = VC3( worldMin.x, planeY, worldMax.y ) - position; float d1 = p1.GetLength(); float d2 = p2.GetLength(); float d3 = p3.GetLength(); float d4 = p4.GetLength(); float maxRange = 0.0f; maxRange = MAX( maxRange, d1 ); maxRange = MAX( maxRange, d2 ); maxRange = MAX( maxRange, d3 ); maxRange = MAX( maxRange, d4 ); //maxRange = sqrtf(maxRange); // Calculate FOV of the camera. VC3 planeCenter = VC3( (worldMin.x + worldMax.x) * 0.5f, planeY, (worldMin.y + worldMax.y) * 0.5f ); VC3 camVec = planeCenter - position; camVec.Normalize(); float minDot = 10000.0f; float t1 = camVec.GetDotWith( p1 ) / d1; float t2 = camVec.GetDotWith( p2 ) / d2; float t3 = camVec.GetDotWith( p3 ) / d3; float t4 = camVec.GetDotWith( p4 ) / d4; minDot = MIN( minDot, t1 ); minDot = MIN( minDot, t2 ); minDot = MIN( minDot, t3 ); minDot = MIN( minDot, t4 ); float maxAngle = acosf( minDot ); // Place camera to light position camera.SetPosition(position); camera.SetUpVec(VC3(0.f, 0.f, 1.f)); // Point camera at light plane center camera.SetTarget(planeCenter); camera.SetFieldOfView( maxAngle ); camera.SetVisibilityRange( maxRange ); } D3DXMATRIX cameraMatrix(cameraView); float det = D3DXMatrixDeterminant(&cameraMatrix); D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix); unsigned int tweakRange = 1; float bias = 0.f; float currentBias = 0.f; for(int i = 0; i < 2; ++i) { D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up); if(i == 1) currentBias = 0; // Tweak matrix float soffsetX = 0.5f; float soffsetY = 0.5f; float scale = 0.5f; D3DXMATRIX shadowTweak( scale, 0.0f, 0.0f, 0.0f, 0.0f, -scale, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, soffsetX, soffsetY, currentBias, 1.0f ); D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak); D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]); D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection); shaderProjection[i] = shadowProjection[i]; D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]); } { float xf = (1.f / resolutionX * .5f); float yf = (1.f / resolutionY * .5f); float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf; float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf; D3DXMATRIX shadowTweak( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, -scaleY, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, sX, sY, bias, 1.0f ); D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak); D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection); } }
bool Storm3D_SpotlightShared::setScissorRect(Storm3D_Camera &camera, const VC2I &screenSize) { D3DXMATRIX light; D3DXVECTOR3 lightPosition(position.x, position.y, position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(direction.x, direction.y, direction.z); D3DXMatrixLookAtLH(&light, &lightPosition, &lookAt, &up); D3DXVECTOR3 v[5]; v[0] = D3DXVECTOR3(0, 0, 0); v[1] = D3DXVECTOR3(0, 0, 1.f); v[2] = D3DXVECTOR3(0, 0, 1.f); v[3] = D3DXVECTOR3(0, 0, 1.f); v[4] = D3DXVECTOR3(0, 0, 1.f); int minX = screenSize.x; int minY = screenSize.y; int maxX = 0; int maxY = 0; float det = D3DXMatrixDeterminant(&light); D3DXMatrixInverse(&light, &det, &light); float angle = D3DXToRadian(fov) * .5f; for(int i = 0; i <= 4; ++i) { if(i > 0) { float z = v[i].z; if(i == 1 || i == 2) { v[i].x = z * sinf(angle); v[i].z = z * cosf(angle); } else { v[i].x = z * sinf(-angle); v[i].z = z * cosf(-angle); } if(i == 1 || i == 3) v[i].y = z * sinf(angle); else v[i].y = z * sinf(-angle); float scale = range / cosf(angle); v[i] *= scale; } D3DXVec3TransformCoord(&v[i], &v[i], &light); } const Frustum &frustum = camera.getFrustum(); calculateLineToScissor(toVC3(v[0]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[0]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[1]), toVC3(v[2]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[2]), toVC3(v[3]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[3]), toVC3(v[4]), frustum, camera, screenSize, minX, minY, maxX, maxY); calculateLineToScissor(toVC3(v[4]), toVC3(v[1]), frustum, camera, screenSize, minX, minY, maxX, maxY); /* VC3 cameraPos = camera.GetPosition(); VC3 cameraPosResult; float cameraRhw = 0, cameraRealZ = 0; bool cameraVisible = camera.GetTransformedToScreen(cameraPos, cameraPosResult, cameraRhw, cameraRealZ); for(i = 0; i <= 4; ++i) { VC3 source(v[i].x, v[i].y, v[i].z); VC3 result; float rhw = 0, realZ = 0; bool inFront = camera.GetTransformedToScreen(source, result, rhw, realZ); // HAX HAX! result.x = std::max(0.f, result.x); result.y = std::max(0.f, result.y); result.x = std::min(1.f, result.x); result.y = std::min(1.f, result.y); //if(fabsf(rhw) < 0.0001f) // continue; bool flip = false; if(realZ < cameraRealZ) flip = true; if(flip) { result.x = 1.f - result.x; result.y = 1.f - result.y; //minX = 0; //minY = 0; //maxX = screenSize.x; //maxY = screenSize.y; } int x = int(result.x * screenSize.x); int y = int(result.y * screenSize.y); maxX = std::max(x, maxX); maxY = std::max(y, maxY); minX = std::min(x, minX); minY = std::min(y, minY); } */ if(maxX > screenSize.x) maxX = screenSize.x; if(maxY > screenSize.y) maxY = screenSize.y; if(minX < 0) minX = 0; if(minY < 0) minY = 0; RECT rc; rc.left = minX; rc.top = minY; rc.right = maxX; rc.bottom = maxY; if(rc.left < rc.right && rc.top < rc.bottom) { device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); } else { RECT rc; rc.left = 0; rc.top = 0; rc.right = 1; rc.bottom = 1; device.SetScissorRect(&rc); device.SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); return false; } return true; }
float float4x4::Determinant() { return D3DXMatrixDeterminant(this); }
void Storm3D_Spotlight::renderCone(Storm3D_Camera &camera, float timeFactor, bool renderGlows) { if(!data->hasCone || !data->hasShadows || !data->shadowMap) return; bool normalPass = !data->coneUpdated; if(data->hasCone && data->updateCone && !data->coneUpdated) { data->createCone(); data->coneUpdated = true; } D3DXVECTOR3 lightPosition(data->properties.position.x, data->properties.position.y, data->properties.position.z); D3DXVECTOR3 up(0, 1.f, 0); D3DXVECTOR3 lookAt = lightPosition; lookAt += D3DXVECTOR3(data->properties.direction.x, data->properties.direction.y, data->properties.direction.z); D3DXMATRIX tm; D3DXMatrixLookAtLH(&tm, &lightPosition, &lookAt, &up); VC3 cameraDir = camera.GetDirection(); cameraDir.Normalize(); D3DXVECTOR3 direction(cameraDir.x, cameraDir.y, cameraDir.z); D3DXVec3TransformNormal(&direction, &direction, &tm); Storm3D_ShaderManager::GetSingleton()->setSpot(data->properties.color, data->properties.position, data->properties.direction, data->properties.range, .1f); Storm3D_ShaderManager::GetSingleton()->setTextureTm(data->properties.shaderProjection[0]); Storm3D_ShaderManager::GetSingleton()->setSpotTarget(data->properties.targetProjection); float det = D3DXMatrixDeterminant(&tm); D3DXMatrixInverse(&tm, &det, &tm); Storm3D_ShaderManager::GetSingleton()->SetWorldTransform(data->device, tm, true); if(data->shadowMap && data->shadowMap->hasInitialized()) data->shadowMap->apply(0); if(data->coneTexture) { data->coneTexture->AnimateVideo(); data->coneTexture->Apply(3); if(type == AtiBuffer || type == AtiFloatBuffer) data->coneTexture->Apply(4); else data->coneTexture->Apply(1); } if(type == AtiBuffer) { if(data->coneTexture) data->coneAtiPixelShader_Texture->apply(); else data->coneAtiPixelShader_NoTexture->apply(); } else if(type == AtiFloatBuffer) { if(data->coneTexture) data->coneAtiFloatPixelShader_Texture->apply(); else data->coneAtiFloatPixelShader_NoTexture->apply(); } else { if(data->coneTexture) data->coneNvPixelShader_Texture->apply(); else data->coneNvPixelShader_NoTexture->apply(); } float colorMul = data->coneColorMultiplier; float colorData[4] = { data->properties.color.r * colorMul, data->properties.color.g * colorMul, data->properties.color.b * colorMul, 1.f }; if(renderGlows) { if(normalPass) { colorData[0] *= 0.2f; colorData[1] *= 0.2f; colorData[2] *= 0.2f; colorData[3] *= 0.2f; } else { colorData[0] *= 0.4f; colorData[1] *= 0.4f; colorData[2] *= 0.4f; colorData[3] *= 0.4f; } } data->device.SetVertexShaderConstantF(9, colorData, 1); float bias = 0.005f; float directionData[4] = { -direction.x, -direction.y, -direction.z, bias }; data->device.SetVertexShaderConstantF(10, directionData, 1); for(int i = 0; i < 2; ++i) { data->angle[i] += data->speed[i] * timeFactor; D3DXVECTOR3 center(0.5f, 0.5f, 0.f); D3DXQUATERNION quat1; D3DXQuaternionRotationYawPitchRoll(&quat1, 0, 0, data->angle[i]); D3DXMATRIX rot1; D3DXMatrixAffineTransformation(&rot1, 1.f, ¢er, &quat1, 0); D3DXMatrixTranspose(&rot1, &rot1); if(i == 0) data->device.SetVertexShaderConstantF(16, rot1, 3); else data->device.SetVertexShaderConstantF(19, rot1, 3); } frozenbyte::storm::enableMipFiltering(data->device, 0, 0, false); data->coneVertexBuffer.apply(data->device, 0); data->coneIndexBuffer.render(data->device, CONE_FACES, CONE_VERTICES); frozenbyte::storm::enableMipFiltering(data->device, 0, 0, true); }
D3DXMATRIX Interpolate( const D3DXMATRIX& MatrixA, const D3DXMATRIX& MatrixB, float lamda) { D3DXMATRIX iMat = MatrixA; D3DXMATRIX result = MatrixB; // Inverse of MatrixA FLOAT determinant = D3DXMatrixDeterminant(&iMat); D3DXMatrixInverse(&iMat, &determinant, &iMat); // Remove MatrixA's transformation from MatrixB result *= iMat; // iMat is now the intermediary transformation from MatrixA to MatrixB // ie: iMat * MatrixA = MatrixB iMat = result; // The trace of our matrix float trace = 1.0f + iMat._11 + iMat._22 + iMat._33; float quatResult[4]; // Calculate the quaternion of iMat // If trace is greater than 0, but consider small values that // might result in 0 when operated upon due to floating point error if( trace > 0.00000001 ) { float S = sqrt(trace)*2; quatResult[0] = (iMat._32 - iMat._23) / S; quatResult[1] = (iMat._13 - iMat._31) / S; quatResult[2] = (iMat._21 - iMat._12) / S; quatResult[3] = 0.25f * S; } else { if( iMat._11 > iMat._22 && iMat._11 > iMat._33 ) { float S = float(sqrt( 1.0 + iMat._11 - iMat._22 - iMat._33 ) * 2); quatResult[0] = 0.25f * S; quatResult[1] = (iMat._21 + iMat._12) / S; quatResult[2] = (iMat._13 + iMat._31) / S; quatResult[3] = (iMat._32 - iMat._23) / S; } else if( iMat._22 > iMat._33 ) { float S = float(sqrt( 1.0 + iMat._22 - iMat._11 - iMat._33 ) * 2); quatResult[0] = (iMat._21 + iMat._12) / S; quatResult[1] = 0.25f * S; quatResult[2] = (iMat._32 + iMat._23) / S; quatResult[3] = (iMat._13 - iMat._31) / S; } else { float S = float(sqrt( 1.0 + iMat._33 - iMat._11 - iMat._22 ) * 2); quatResult[0] = (iMat._13 + iMat._31) / S; quatResult[1] = (iMat._32 + iMat._23) / S; quatResult[2] = 0.25f * S; quatResult[3] = (iMat._21 - iMat._12) / S; } } // Get the magnitude of our quaternion float quatMagnitude = sqrt( quatResult[0]*quatResult[0] + quatResult[1]*quatResult[1] + quatResult[2]*quatResult[2] + quatResult[3]*quatResult[3] ); // Normalize our quaternion float quatNormalized[4] = { quatResult[0]/quatMagnitude, quatResult[1]/quatMagnitude, quatResult[2]/quatMagnitude, quatResult[3]/quatMagnitude }; // Calculate the angles relevant to our quaternion float cos_a = quatNormalized[3]; float angle = acos( cos_a ) * 2; float sin_a = float(sqrt( 1.0 - cos_a * cos_a )); // If there was no rotation between matrices, calculation // of the rotation matrix will end badly. So just do the linear // interpolation of the translation component and return if( angle == 0.0 ) { result = MatrixA; result.m[3][0] = MatrixA.m[3][0] + ((MatrixB.m[3][0]-MatrixA.m[3][0])*lamda); result.m[3][1] = MatrixA.m[3][1] + ((MatrixB.m[3][1]-MatrixA.m[3][1])*lamda); result.m[3][2] = MatrixA.m[3][2] + ((MatrixB.m[3][2]-MatrixA.m[3][2])*lamda); return result; } // Our axis of abitrary rotation D3DXVECTOR3 axis; if( fabs( sin_a ) < 0.0005 ) sin_a = 1; axis.x = quatNormalized[0] / sin_a; axis.y = quatNormalized[1] / sin_a; axis.z = quatNormalized[2] / sin_a; // Get the portion of the angle to rotate by angle *= lamda; D3DXVec3Normalize(&axis, &axis); // Calculate the quaternion for our new (partial) angle of rotation sin_a = sin( angle / 2 ); cos_a = cos( angle / 2 ); quatNormalized[0] = axis.x * sin_a; quatNormalized[1] = axis.y * sin_a; quatNormalized[2] = axis.z * sin_a; quatNormalized[3] = cos_a; quatMagnitude = sqrt( quatNormalized[0]*quatNormalized[0] + quatNormalized[1]*quatNormalized[1] + quatNormalized[2]*quatNormalized[2] + quatNormalized[3]*quatNormalized[3] ); quatNormalized[0] /= quatMagnitude; quatNormalized[1] /= quatMagnitude; quatNormalized[2] /= quatMagnitude; quatNormalized[3] /= quatMagnitude; // Calculate our partial rotation matrix float xx = quatNormalized[0] * quatNormalized[0]; float xy = quatNormalized[0] * quatNormalized[1]; float xz = quatNormalized[0] * quatNormalized[2]; float xw = quatNormalized[0] * quatNormalized[3]; float yy = quatNormalized[1] * quatNormalized[1]; float yz = quatNormalized[1] * quatNormalized[2]; float yw = quatNormalized[1] * quatNormalized[3]; float zz = quatNormalized[2] * quatNormalized[2]; float zw = quatNormalized[2] * quatNormalized[3]; result._11 = 1 - 2 * ( yy + zz ); result._12 = 2 * ( xy - zw ); result._13 = 2 * ( xz + yw ); result._21 = 2 * ( xy + zw ); result._22 = 1 - 2 * ( xx + zz ); result._23 = 2 * ( yz - xw ); result._31 = 2 * ( xz - yw ); result._32 = 2 * ( yz + xw ); result._33 = 1 - 2 * ( xx + yy ); result._14 = result._24 = result._34 = result._41 = result._42 = result._43 = 0; result._44 = 1; // Combine our partial rotation with MatrixA result *= MatrixA; // Linear interpolation of the translation components of the matrices result.m[3][0] = MatrixA.m[3][0] + ((MatrixB.m[3][0]-MatrixA.m[3][0])*lamda); result.m[3][1] = MatrixA.m[3][1] + ((MatrixB.m[3][1]-MatrixA.m[3][1])*lamda); result.m[3][2] = MatrixA.m[3][2] + ((MatrixB.m[3][2]-MatrixA.m[3][2])*lamda); return result; }