UtilityMath::S_Matrix3x3<T> UtilityMath::S_Matrix3x3<T>::GetInvert() const { S_Matrix3x3 inverseMatrix(*this); inverseMatrix.Invert(); return inverseMatrix; }
int main(void) { for(int s = 0; s < 26; ++ s) repr['a' + s] = s + 1; scanf("%d", &tests); for(int t = 0; t < tests; ++ t) { scanf("%d %s", &MOD, buffer); len = 0; while(buffer[len]) ++ len; inverseMatrix(len); for(int h = 0; h < len; ++ h) { res = 0; for(int w = 0; w < len; ++ w) res = (res + matrix[h][len + w] * repr[(int)buffer[w]]) % MOD; printf("%d ", res); } puts(""); } return 0; }
int CKLBLuaLibMatrix::luaInverseMatrix(lua_State * L) { CLuaState lua(L); MATRIX * pMat = getMatPointer(lua, 1); bool bResult = inverseMatrix(pMat); lua.retBoolean(bResult); return 1; }
void ComputeApproximateNearFarPlaneDist(const float3 &CameraPos, const float4x4 &ViewMatr, const float4x4 &ProjMatr, const float3 &EarthCenter, float fEarthRadius, float fMinRadius, float fMaxRadius, float &fNearPlaneZ, float &fFarPlaneZ) { float4x4 ViewProjMatr = ViewMatr * ProjMatr; float4x4 ViewProjInv = inverseMatrix(ViewProjMatr); // Compute maximum view distance for the current camera altitude float3 f3CameraGlobalPos = CameraPos - EarthCenter; float fCameraElevationSqr = dot(f3CameraGlobalPos, f3CameraGlobalPos); float fMaxViewDistance = (float)(sqrt( (double)fCameraElevationSqr - (double)fEarthRadius*fEarthRadius ) + sqrt( (double)fMaxRadius*fMaxRadius - (double)fEarthRadius*fEarthRadius )); float fCameraElev = sqrt(fCameraElevationSqr); fNearPlaneZ = 50.f; if( fCameraElev > fMaxRadius ) { // Adjust near clipping plane fNearPlaneZ = (fCameraElev - fMaxRadius) / sqrt( 1 + 1.f/(ProjMatr._11*ProjMatr._11) + 1.f/(ProjMatr._22*ProjMatr._22) ); } fNearPlaneZ = std::max(fNearPlaneZ, 50.f); fFarPlaneZ = 1000; const int iNumTestDirections = 5; for(int i=0; i<iNumTestDirections; ++i) for(int j=0; j<iNumTestDirections; ++j) { float3 PosPS, PosWS, DirFromCamera; PosPS.x = (float)i / (float)(iNumTestDirections-1) * 2.f - 1.f; PosPS.y = (float)j / (float)(iNumTestDirections-1) * 2.f - 1.f; PosPS.z = 0; // Far plane is at 0 in complimentary depth buffer PosWS = PosPS * ViewProjInv; DirFromCamera = PosWS - CameraPos; DirFromCamera = normalize(DirFromCamera); float2 IsecsWithBottomBoundSphere; GetRaySphereIntersection(CameraPos, DirFromCamera, EarthCenter, fMinRadius, IsecsWithBottomBoundSphere); float fNearIsecWithBottomSphere = IsecsWithBottomBoundSphere.x > 0 ? IsecsWithBottomBoundSphere.x : IsecsWithBottomBoundSphere.y; if( fNearIsecWithBottomSphere > 0 ) { // The ray hits the Earth. Use hit point to compute camera space Z float3 HitPointWS = CameraPos + DirFromCamera*fNearIsecWithBottomSphere; float3 HitPointCamSpace; HitPointCamSpace = HitPointWS * ViewMatr; fFarPlaneZ = std::max(fFarPlaneZ, HitPointCamSpace.z); } else { // The ray misses the Earth. In that case the whole earth could be seen fFarPlaneZ = fMaxViewDistance; } } }
// Render a frame void AtmosphereSample::Render() { float4x4 mViewProj = m_mCameraView * m_mCameraProj; LightAttribs LightAttrs; LightAttrs.f4DirOnLight = -m_f3LightDir; LightAttrs.f4DirOnLight.w = 0; float4 f4ExtraterrestrialSunColor = float4(10,10,10,10); LightAttrs.f4ExtraterrestrialSunColor = f4ExtraterrestrialSunColor;// *m_fScatteringScale; LightAttrs.f4AmbientLight = float4( 0, 0, 0, 0 ); // m_iFirstCascade must be initialized before calling RenderShadowMap()! m_PPAttribs.m_iFirstCascade = std::min(m_PPAttribs.m_iFirstCascade, m_TerrainRenderParams.m_iNumShadowCascades - 1); m_PPAttribs.m_fFirstCascade = (float)m_PPAttribs.m_iFirstCascade; RenderShadowMap(m_pImmediateContext, LightAttrs, m_mCameraView, m_mCameraProj); LightAttrs.ShadowAttribs.bVisualizeCascades = m_bVisualizeCascades ? TRUE : FALSE; // Calculate location of the sun on the screen float4 &f4LightPosPS = LightAttrs.f4LightScreenPos; f4LightPosPS = LightAttrs.f4DirOnLight * mViewProj; f4LightPosPS.x /= f4LightPosPS.w; f4LightPosPS.y /= f4LightPosPS.w; f4LightPosPS.z /= f4LightPosPS.w; float fDistToLightOnScreen = length( (float2&)f4LightPosPS ); float fMaxDist = 100; if( fDistToLightOnScreen > fMaxDist ) (float2&)f4LightPosPS *= fMaxDist/fDistToLightOnScreen; const auto& SCDesc = m_pSwapChain->GetDesc(); // Note that in fact the outermost visible screen pixels do not lie exactly on the boundary (+1 or -1), but are biased by // 0.5 screen pixel size inwards. Using these adjusted boundaries improves precision and results in // smaller number of pixels which require inscattering correction LightAttrs.bIsLightOnScreen = fabs(f4LightPosPS.x) <= 1.f - 1.f/(float)SCDesc.Width && fabs(f4LightPosPS.y) <= 1.f - 1.f/(float)SCDesc.Height; { MapHelper<LightAttribs> pLightAttribs( m_pImmediateContext, m_pcbLightAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); *pLightAttribs = LightAttrs; } // The first time GetAmbientSkyLightSRV() is called, the ambient sky light texture // is computed and render target is set. So we need to query the texture before setting // render targets auto *pAmbientSkyLightSRV = m_pLightSctrPP->GetAmbientSkyLightSRV(m_pDevice, m_pImmediateContext); m_pImmediateContext->SetRenderTargets( 0, nullptr, nullptr ); const float ClearColor[] = { 0.350f, 0.350f, 0.350f, 1.0f }; const float Zero[] = { 0.f, 0.f, 0.f, 0.f }; m_pImmediateContext->ClearRenderTarget(nullptr, m_bEnableLightScattering ? Zero : ClearColor); ITextureView *pRTV = nullptr, *pDSV = nullptr; if( m_bEnableLightScattering ) { pRTV = m_pOffscreenColorBuffer->GetDefaultView( TEXTURE_VIEW_RENDER_TARGET ); pDSV = m_pOffscreenDepthBuffer->GetDefaultView( TEXTURE_VIEW_DEPTH_STENCIL ); m_pImmediateContext->SetRenderTargets( 1, &pRTV, pDSV ); m_pImmediateContext->ClearRenderTarget(pRTV, Zero); } else { pRTV = nullptr; pDSV = nullptr; m_pImmediateContext->SetRenderTargets( 0, nullptr, nullptr ); } m_pImmediateContext->ClearDepthStencil(pDSV, CLEAR_DEPTH_FLAG, 1.f); { MapHelper<CameraAttribs> CamAttribs( m_pImmediateContext, m_pcbCameraAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); CamAttribs->mViewProjT = transposeMatrix( mViewProj ); CamAttribs->mProjT = transposeMatrix( m_mCameraProj ); CamAttribs->mViewProjInvT = transposeMatrix( inverseMatrix(mViewProj) ); float fNearPlane = 0.f, fFarPlane = 0.f; GetNearFarPlaneFromProjMatrix( m_mCameraProj, fNearPlane, fFarPlane, m_bIsDXDevice); CamAttribs->fNearPlaneZ = fNearPlane; CamAttribs->fFarPlaneZ = fFarPlane * 0.999999f; CamAttribs->f4CameraPos = m_f3CameraPos; } // Render terrain auto *pPrecomputedNetDensitySRV = m_pLightSctrPP->GetPrecomputedNetDensitySRV(); m_TerrainRenderParams.DstRTVFormat = m_bEnableLightScattering ? m_pOffscreenColorBuffer->GetDesc().Format : m_pSwapChain->GetDesc().ColorBufferFormat; m_EarthHemisphere.Render( m_pImmediateContext, m_TerrainRenderParams, m_f3CameraPos, mViewProj, m_pShadowMapSRV, pPrecomputedNetDensitySRV, pAmbientSkyLightSRV, false); if( m_bEnableLightScattering ) { FrameAttribs FrameAttribs; FrameAttribs.pDevice = m_pDevice; FrameAttribs.pDeviceContext = m_pImmediateContext; FrameAttribs.dElapsedTime = m_fElapsedTime; FrameAttribs.pLightAttribs = &LightAttrs; m_PPAttribs.m_iNumCascades = m_TerrainRenderParams.m_iNumShadowCascades; m_PPAttribs.m_fNumCascades = (float)m_TerrainRenderParams.m_iNumShadowCascades; FrameAttribs.pcbLightAttribs = m_pcbLightAttribs; FrameAttribs.pcbCameraAttribs = m_pcbCameraAttribs; m_PPAttribs.m_fMaxShadowMapStep = static_cast<float>(m_uiShadowMapResolution / 4); m_PPAttribs.m_f2ShadowMapTexelSize = float2( 1.f / static_cast<float>(m_uiShadowMapResolution), 1.f / static_cast<float>(m_uiShadowMapResolution) ); m_PPAttribs.m_uiShadowMapResolution = m_uiShadowMapResolution; // During the ray marching, on each step we move by the texel size in either horz // or vert direction. So resolution of min/max mipmap should be the same as the // resolution of the original shadow map m_PPAttribs.m_uiMinMaxShadowMapResolution = m_uiShadowMapResolution; m_PPAttribs.m_uiInitialSampleStepInSlice = std::min( m_PPAttribs.m_uiInitialSampleStepInSlice, m_PPAttribs.m_uiMaxSamplesInSlice ); m_PPAttribs.m_uiEpipoleSamplingDensityFactor = std::min( m_PPAttribs.m_uiEpipoleSamplingDensityFactor, m_PPAttribs.m_uiInitialSampleStepInSlice ); FrameAttribs.ptex2DSrcColorBufferSRV = m_pOffscreenColorBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); FrameAttribs.ptex2DSrcColorBufferRTV = m_pOffscreenColorBuffer->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET); FrameAttribs.ptex2DSrcDepthBufferSRV = m_pOffscreenDepthBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); FrameAttribs.ptex2DSrcDepthBufferDSV = m_pOffscreenDepthBuffer->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL); FrameAttribs.ptex2DShadowMapSRV = m_pShadowMapSRV; FrameAttribs.pDstRTV = 0;// mpBackBufferRTV; // Then perform the post processing, swapping the inverseworld view projection matrix axes. m_pLightSctrPP->PerformPostProcessing(FrameAttribs, m_PPAttribs); } }
void AtmosphereSample::RenderShadowMap(IDeviceContext *pContext, LightAttribs &LightAttribs, const float4x4 &mCameraView, const float4x4 &mCameraProj ) { ShadowMapAttribs& ShadowMapAttribs = LightAttribs.ShadowAttribs; float3 v3DirOnLight = (float3&)LightAttribs.f4DirOnLight; float3 v3LightDirection = -v3DirOnLight; // Declare working vectors float3 vLightSpaceX, vLightSpaceY, vLightSpaceZ; // Compute an inverse vector for the direction on the sun vLightSpaceZ = v3LightDirection; // And a vector for X light space vLightSpaceX = float3( 1.0f, 0.0, 0.0 ); // Compute the cross products vLightSpaceY = cross(vLightSpaceX, vLightSpaceZ); vLightSpaceX = cross(vLightSpaceZ, vLightSpaceY); // And then normalize them vLightSpaceX = normalize( vLightSpaceX ); vLightSpaceY = normalize( vLightSpaceY ); vLightSpaceZ = normalize( vLightSpaceZ ); // Declare a world to light space transformation matrix // Initialize to an identity matrix float4x4 WorldToLightViewSpaceMatr = ViewMatrixFromBasis( vLightSpaceX, vLightSpaceY, vLightSpaceZ ); ShadowMapAttribs.mWorldToLightViewT = transposeMatrix( WorldToLightViewSpaceMatr ); float3 f3CameraPosInLightSpace = m_f3CameraPos * WorldToLightViewSpaceMatr; float fMainCamNearPlane, fMainCamFarPlane; GetNearFarPlaneFromProjMatrix( mCameraProj, fMainCamNearPlane, fMainCamFarPlane, m_bIsDXDevice); for(int i=0; i < MAX_CASCADES; ++i) ShadowMapAttribs.fCascadeCamSpaceZEnd[i] = +FLT_MAX; // Render cascades for(int iCascade = 0; iCascade < m_TerrainRenderParams.m_iNumShadowCascades; ++iCascade) { auto &CurrCascade = ShadowMapAttribs.Cascades[iCascade]; float4x4 CascadeFrustumProjMatrix; float &fCascadeFarZ = ShadowMapAttribs.fCascadeCamSpaceZEnd[iCascade]; float fCascadeNearZ = (iCascade == 0) ? fMainCamNearPlane : ShadowMapAttribs.fCascadeCamSpaceZEnd[iCascade-1]; fCascadeFarZ = fMainCamFarPlane; if (iCascade < m_TerrainRenderParams.m_iNumShadowCascades-1) { float ratio = fMainCamFarPlane / fMainCamNearPlane; float power = (float)(iCascade+1) / (float)m_TerrainRenderParams.m_iNumShadowCascades; float logZ = fMainCamNearPlane * pow(ratio, power); float range = fMainCamFarPlane - fMainCamNearPlane; float uniformZ = fMainCamNearPlane + range * power; fCascadeFarZ = m_fCascadePartitioningFactor * (logZ - uniformZ) + uniformZ; } float fMaxLightShaftsDist = 3e+5f; // Ray marching always starts at the camera position, not at the near plane. // So we must make sure that the first cascade used for ray marching covers the camera position CurrCascade.f4StartEndZ.x = (iCascade == m_PPAttribs.m_iFirstCascade) ? 0 : std::min(fCascadeNearZ, fMaxLightShaftsDist); CurrCascade.f4StartEndZ.y = std::min(fCascadeFarZ, fMaxLightShaftsDist); CascadeFrustumProjMatrix = mCameraProj; SetNearFarClipPlanes( CascadeFrustumProjMatrix, fCascadeNearZ, fCascadeFarZ, m_bIsDXDevice ); float4x4 CascadeFrustumViewProjMatr = mCameraView * CascadeFrustumProjMatrix; float4x4 CascadeFrustumProjSpaceToWorldSpace = inverseMatrix(CascadeFrustumViewProjMatr); float4x4 CascadeFrustumProjSpaceToLightSpace = CascadeFrustumProjSpaceToWorldSpace * WorldToLightViewSpaceMatr; // Set reference minimums and maximums for each coordinate float3 f3MinXYZ(f3CameraPosInLightSpace), f3MaxXYZ(f3CameraPosInLightSpace); // First cascade used for ray marching must contain camera within it if( iCascade != m_PPAttribs.m_iFirstCascade ) { f3MinXYZ = float3(+FLT_MAX, +FLT_MAX, +FLT_MAX); f3MaxXYZ = float3(-FLT_MAX, -FLT_MAX, -FLT_MAX); } for(int iClipPlaneCorner=0; iClipPlaneCorner < 8; ++iClipPlaneCorner) { float3 f3PlaneCornerProjSpace( (iClipPlaneCorner & 0x01) ? +1.f : - 1.f, (iClipPlaneCorner & 0x02) ? +1.f : - 1.f, // Since we use complimentary depth buffering, // far plane has depth 0 (iClipPlaneCorner & 0x04) ? 1.f : (m_bIsDXDevice ? 0.f : -1.f)); float3 f3PlaneCornerLightSpace = f3PlaneCornerProjSpace * CascadeFrustumProjSpaceToLightSpace; f3MinXYZ = min(f3MinXYZ, f3PlaneCornerLightSpace); f3MaxXYZ = max(f3MaxXYZ, f3PlaneCornerLightSpace); } // It is necessary to ensure that shadow-casting patches, which are not visible // in the frustum, are still rendered into the shadow map f3MinXYZ.z -= AirScatteringAttribs().fEarthRadius * sqrt(2.f); // Align cascade extent to the closest power of two float fShadowMapDim = (float)m_uiShadowMapResolution; float fCascadeXExt = (f3MaxXYZ.x - f3MinXYZ.x) * (1 + 1.f/fShadowMapDim); float fCascadeYExt = (f3MaxXYZ.y - f3MinXYZ.y) * (1 + 1.f/fShadowMapDim); const float fExtStep = 2.f; fCascadeXExt = pow( fExtStep, ceil( log(fCascadeXExt)/log(fExtStep) ) ); fCascadeYExt = pow( fExtStep, ceil( log(fCascadeYExt)/log(fExtStep) ) ); // Align cascade center with the shadow map texels to alleviate temporal aliasing float fCascadeXCenter = (f3MaxXYZ.x + f3MinXYZ.x)/2.f; float fCascadeYCenter = (f3MaxXYZ.y + f3MinXYZ.y)/2.f; float fTexelXSize = fCascadeXExt / fShadowMapDim; float fTexelYSize = fCascadeXExt / fShadowMapDim; fCascadeXCenter = floor(fCascadeXCenter/fTexelXSize) * fTexelXSize; fCascadeYCenter = floor(fCascadeYCenter/fTexelYSize) * fTexelYSize; // Compute new cascade min/max xy coords f3MaxXYZ.x = fCascadeXCenter + fCascadeXExt/2.f; f3MinXYZ.x = fCascadeXCenter - fCascadeXExt/2.f; f3MaxXYZ.y = fCascadeYCenter + fCascadeYExt/2.f; f3MinXYZ.y = fCascadeYCenter - fCascadeYExt/2.f; CurrCascade.f4LightSpaceScale.x = 2.f / (f3MaxXYZ.x - f3MinXYZ.x); CurrCascade.f4LightSpaceScale.y = 2.f / (f3MaxXYZ.y - f3MinXYZ.y); CurrCascade.f4LightSpaceScale.z = (m_bIsDXDevice ? 1.f : 2.f) / (f3MaxXYZ.z - f3MinXYZ.z); // Apply bias to shift the extent to [-1,1]x[-1,1]x[0,1] for DX or to [-1,1]x[-1,1]x[-1,1] for GL // Find bias such that f3MinXYZ -> (-1,-1,0) for DX or (-1,-1,-1) for GL CurrCascade.f4LightSpaceScaledBias.x = -f3MinXYZ.x * CurrCascade.f4LightSpaceScale.x - 1.f; CurrCascade.f4LightSpaceScaledBias.y = -f3MinXYZ.y * CurrCascade.f4LightSpaceScale.y - 1.f; CurrCascade.f4LightSpaceScaledBias.z = -f3MinXYZ.z * CurrCascade.f4LightSpaceScale.z + (m_bIsDXDevice ? 0.f : -1.f); float4x4 ScaleMatrix = scaleMatrix( CurrCascade.f4LightSpaceScale.x, CurrCascade.f4LightSpaceScale.y, CurrCascade.f4LightSpaceScale.z ); float4x4 ScaledBiasMatrix = translationMatrix( CurrCascade.f4LightSpaceScaledBias.x, CurrCascade.f4LightSpaceScaledBias.y, CurrCascade.f4LightSpaceScaledBias.z ) ; // Note: bias is applied after scaling! float4x4 CascadeProjMatr = ScaleMatrix * ScaledBiasMatrix; //D3DXMatrixOrthoOffCenterLH( &m_LightOrthoMatrix, MinX, MaxX, MinY, MaxY, MaxZ, MinZ); // Adjust the world to light space transformation matrix float4x4 WorldToLightProjSpaceMatr = WorldToLightViewSpaceMatr * CascadeProjMatr; float4x4 ProjToUVScale, ProjToUVBias; if( m_bIsDXDevice ) { ProjToUVScale = scaleMatrix( 0.5f, -0.5f, 1.f ); ProjToUVBias = translationMatrix( 0.5f, 0.5f, 0.f ); } else { ProjToUVScale = scaleMatrix( 0.5f, 0.5f, 0.5f ); ProjToUVBias = translationMatrix( 0.5f, 0.5f, 0.5f ); } float4x4 WorldToShadowMapUVDepthMatr = WorldToLightProjSpaceMatr * ProjToUVScale * ProjToUVBias; ShadowMapAttribs.mWorldToShadowMapUVDepthT[iCascade] = transposeMatrix( WorldToShadowMapUVDepthMatr ); m_pImmediateContext->SetRenderTargets( 0, nullptr, m_pShadowMapDSVs[iCascade] ); m_pImmediateContext->ClearDepthStencil( m_pShadowMapDSVs[iCascade], CLEAR_DEPTH_FLAG, 1.f ); // Render terrain to shadow map { MapHelper<CameraAttribs> CamAttribs( m_pImmediateContext, m_pcbCameraAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); CamAttribs->mViewProjT = transposeMatrix( WorldToLightProjSpaceMatr ); } m_EarthHemisphere.Render(m_pImmediateContext, m_TerrainRenderParams, m_f3CameraPos, WorldToLightProjSpaceMatr, nullptr, nullptr, nullptr, true); } pContext->SetRenderTargets( 0, nullptr, nullptr ); }
//understand the edge vertex computation from [email protected] //ASSUMPTION: eye is along z-axis //vo: volume vertex coords model-space coords //tx: texture vertex coords tex-space coords //axis: axis to slice along world-space coords void vRenderer::renderTexture3D(float sampleFrequency,GLdouble mv[16],float vo[8][3],float tx[8][3],float axis[3]) { float rv[8][3]; //the rotated volume (may include a scale) float maxval = -10; //(tmp) float minval = 10; int minvert = 0, maxvert = 0; GLdouble mvinv[16]; int i, j, k; inverseMatrix(mvinv, mv); //invert model view matrix for(i=0; i<8; ++i){ translateV3(rv[i], mv, vo[i]); //get the rotated vol coords //now get the max and min z in view space if(maxval < MAX(maxval, rv[i][2])){ maxval = MAX(maxval, rv[i][2]); maxvert = i; } if(minval > MIN(minval, rv[i][2])){ minval = MIN(minval, rv[i][2]); minvert = i; //determine the starting corner for slicing } } //find the slice plane point 'sp' (initial) and the slice plane normal 'sn' //sp is the slice starting point, simply the vertex farthest from the eye float sp[3] = {vo[minvert][0], vo[minvert][1], vo[minvert][2]}; // float sp[3] = {vo[maxvert][0], vo[maxvert][1], vo[maxvert][2]}; float vpn[3]; vpn[0] = axis[0]; vpn[1] = axis[1]; vpn[2] = axis[2]; //now calculate sn which is the normalized vpn in the model space //ie where the orginal slices are stored float sn[3]; translateV3(sn, mvinv, vpn); //move vpn to sn (model space); //now normalize this float normsn = (float)sqrt(sn[0]*sn[0] + sn[1]*sn[1] + sn[2]*sn[2]); //normalize sn[0]/=normsn; sn[1]/=normsn; sn[2]/=normsn; //now find the distance we need to slice (|max_vertex - min_vertex|) float maxd[3] = {0, 0, maxval}; //(tmp) only use z-coord (view space) float mind[3] = {0, 0, minval}; //(tmp) ditto (view space) float maxv[3], minv[3]; //(tmp) translateV3(maxv, mvinv, maxd); //translate back to model space translateV3(minv, mvinv, mind); //ditto maxv[0] -= minv[0]; //subtract maxv[1] -= minv[1]; maxv[2] -= minv[2]; //now take the norm of this vector... we have the distance to be sampled //this distance is in the world space float dist = (float)sqrt(maxv[0]*maxv[0] + maxv[1]*maxv[1] + maxv[2]*maxv[2]); #if defined(ADDCGGL) || defined(ADDARBGL) glColor4f(1.0f,1.0f,1.0f,0.01); #else glColor4f(1.0f,1.0f,1.0f,0.1); #endif GlErr("vRenderer","drawVA"); //distance between samples float sampleSpacing = 1.0 / (myVolume->maxDim* sampleFrequency); float del[3] = {sn[0]*sampleSpacing, sn[1]*sampleSpacing, sn[2]*sampleSpacing}; int samples = (int)((dist) / sampleSpacing);//(total distance to be sam //highly un-optimized!!!!!!!!! float poly[6][3]; // for edge intersections float tcoord[6][3]; // for texture intersections float tpoly[6][3]; // for transformed edge intersections int edges; // total number of edge intersections //the dep texture should be scaled glBindTexture(GL_TEXTURE_3D, myVolume->texName); //sp:slice plane point //sn:the slice dirn to cut thru the volume //the above 2 are in world coord space for(i = 0 ; i < samples; ++i){ //for each slice //increment the slice plane point by the slice distance // sp[0] -= del[0]; // sp[1] -= del[1]; // sp[2] -= del[2]; sp[0] += del[0]; sp[1] += del[1]; sp[2] += del[2]; edges = 0; //now check each edge of the volume for intersection with.. //the plane defined by sp & sn //front bottom edge edges += intersect(vo[0], vo[1], tx[0], tx[1], rv[0], rv[1], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front left edge edges += intersect(vo[0], vo[2], tx[0], tx[2], rv[0], rv[2], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front right edge edges += intersect(vo[1], vo[3], tx[1], tx[3], rv[1], rv[3], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //left bottom edge edges += intersect(vo[4], vo[0], tx[4], tx[0], rv[4], rv[0], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //right bottom edge edges += intersect(vo[1], vo[5], tx[1], tx[5], rv[1], rv[5], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front top edge edges += intersect(vo[2], vo[3], tx[2], tx[3], rv[2], rv[3], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back bottom edge edges += intersect(vo[4], vo[5], tx[4], tx[5], rv[4], rv[5], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back left edge edges += intersect(vo[4], vo[6], tx[4], tx[6], rv[4], rv[6], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back right edge edges += intersect(vo[5], vo[7], tx[5], tx[7], rv[5], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back top edge edges += intersect(vo[6], vo[7], tx[6], tx[7], rv[6], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //left top edge edges += intersect(vo[2], vo[6], tx[2], tx[6], rv[2], rv[6], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //right top edge edges += intersect(vo[3], vo[7], tx[3], tx[7], rv[3], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); // B.M.E. Moret & H.D. Shapiro "P to NP" pp. 453 float dx, dy, tt ,theta, cen[2]; //tt= TempTheta cen[0] = cen[1] = 0.0; int next; //rather than swap 3 arrays, only one? int order[6] ={0,1,2,3,4,5}; // order[6] could be an extreemly inefficient way to do this for(j=0; j<edges; ++j){ //find the center of the points cen[0] += tpoly[j][0]; cen[1] += tpoly[j][1]; } //by averaging cen[0]/= edges; cen[1]/= edges; for(j=0; j<edges; ++j){ //for each vertex theta = -10; //find one with largest angle from center.. next = j; for (k= j; k<edges; ++k){ //... and check angle made between other edges dx = tpoly[order[k]][0] - cen[0]; dy = tpoly[order[k]][1] - cen[1]; if( (dx == 0) && (dy == 0)){ //same as center? next = k; cout << "what teh " << endl; break; //out of this for-loop } tt = dy/(ABS(dx) + ABS(dy)); //else compute theta [0-4] if( dx < 0.0 ) tt = (float)(2.0 - tt); //check quadrants 2&3 else if( dy < 0.0 ) tt = (float)(4.0 + tt); //quadrant 4 if( theta <= tt ){ //grab the max theta next = k; theta = tt; } } //end for(k) angle checking // i am using 'tt' as a temp // swap polygon vertex ( is this better than another branch?) // I am not sure wich is worse: swapping 3 vectors for every edge // or: using an array to index into another array??? hmmm.... // should have payed more attention in class int tmp = order[j]; order[j] = order[next]; order[next] = tmp; } //end for(j) edge /angle sort renderSlice(edges, tcoord, poly, order); //}//end else compute convex hull }// end for(i) each slice //now draw each slice view }