UtilityMath::S_Matrix3x3<T> UtilityMath::S_Matrix3x3<T>::GetInvert() const
{
    S_Matrix3x3 inverseMatrix(*this);
    inverseMatrix.Invert();

    return inverseMatrix;
}
Example #2
0
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;
}
Example #3
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 );
}
Example #7
0
//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

 }