summaryrefslogtreecommitdiff
path: root/vgui2/matsys_controls/vtfpreviewpanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vgui2/matsys_controls/vtfpreviewpanel.cpp')
-rw-r--r--vgui2/matsys_controls/vtfpreviewpanel.cpp398
1 files changed, 398 insertions, 0 deletions
diff --git a/vgui2/matsys_controls/vtfpreviewpanel.cpp b/vgui2/matsys_controls/vtfpreviewpanel.cpp
new file mode 100644
index 0000000..abd7afa
--- /dev/null
+++ b/vgui2/matsys_controls/vtfpreviewpanel.cpp
@@ -0,0 +1,398 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#include "matsys_controls/vtfpreviewpanel.h"
+#include "matsys_controls/matsyscontrols.h"
+#include "VGuiMatSurface/IMatSystemSurface.h"
+#include "materialsystem/MaterialSystemUtil.h"
+#include "materialsystem/imaterialsystem.h"
+#include "materialsystem/itexture.h"
+#include "materialsystem/imesh.h"
+#include "tier1/KeyValues.h"
+
+
+using namespace vgui;
+
+
+#define FOV 90.0f
+#define ZNEAR 0.1f
+#define ZFAR 2000.0f
+#define ROTATION_SPEED 120.0f // degrees/sec
+
+//-----------------------------------------------------------------------------
+//
+// VTF Preview panel
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------------
+CVTFPreviewPanel::CVTFPreviewPanel( vgui::Panel *pParent, const char *pName ) :
+ BaseClass( pParent, pName )
+{
+ SetVTF( "//platform/materials/vgui/vtfnotloaded", true );
+ m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
+}
+
+CVTFPreviewPanel::~CVTFPreviewPanel()
+{
+ if ( vgui::surface() && m_nTextureID != -1 )
+ {
+ vgui::surface()->DestroyTextureID( m_nTextureID );
+ m_nTextureID = -1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the current VTF
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::SetVTF( const char *pFullPath, bool bLoadImmediately )
+{
+ m_PreviewTexture.Init( pFullPath, "editor texture" );
+ m_VTFName = pFullPath;
+
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ if ( m_PreviewTexture->IsCubeMap() )
+ {
+ pVMTKeyValues->SetString( "$envmap", pFullPath );
+ }
+ else if ( m_PreviewTexture->IsNormalMap() )
+ {
+ pVMTKeyValues->SetString( "$bumpmap", pFullPath );
+ }
+ else
+ {
+ pVMTKeyValues->SetString( "$basetexture", pFullPath );
+ }
+ pVMTKeyValues->SetInt( "$nocull", 1 );
+ pVMTKeyValues->SetInt( "$nodebug", 1 );
+ m_PreviewMaterial.Init( MaterialSystem()->CreateMaterial( pFullPath, pVMTKeyValues ));
+
+ MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_PreviewMaterial );
+
+ // Reset the camera direction
+ m_vecCameraDirection.Init( 1.0f, 0.0f, 0.0f );
+ m_flLastRotationTime = Plat_FloatTime();
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets the current VTF
+//-----------------------------------------------------------------------------
+const char *CVTFPreviewPanel::GetVTF() const
+{
+ return m_VTFName;
+}
+
+
+//-----------------------------------------------------------------------------
+// Draw a sphere
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi )
+{
+ CMatRenderContextPtr pRenderContext( MaterialSystem() );
+
+ int nVertices = nTheta * nPhi;
+ int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
+
+ pRenderContext->FogMode( MATERIAL_FOG_NONE );
+ pRenderContext->SetNumBoneWeights( 0 );
+ pRenderContext->Bind( m_PreviewMaterial );
+
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+
+ CMeshBuilder meshBuilder;
+ meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nVertices, nIndices );
+
+ //
+ // Build the index buffer.
+ //
+ int i, j;
+ for ( i = 0; i < nPhi; ++i )
+ {
+ for ( j = 0; j < nTheta; ++j )
+ {
+ float u = j / ( float )(nTheta - 1);
+ float v = i / ( float )(nPhi - 1);
+ float theta = ( j != nTheta-1 ) ? 2.0f * M_PI * u : 0.0f;
+ float phi = M_PI * v;
+
+ Vector vecPos;
+ vecPos.x = flRadius * sin(phi) * cos(theta);
+ vecPos.y = flRadius * cos(phi);
+ vecPos.z = -flRadius * sin(phi) * sin(theta);
+
+ Vector vecNormal = vecPos;
+ VectorNormalize( vecNormal );
+
+ Vector4D vecTangentS;
+ Vector vecTangentT;
+ vecTangentS.Init( vecPos.z, -vecPos.x, 0.0f, 1.0f );
+ if ( VectorNormalize( vecTangentS.AsVector3D() ) == 0.0f )
+ {
+ vecTangentS.Init( 1.0f, 0.0f, 0.0f, 1.0f );
+ }
+
+ CrossProduct( vecNormal, vecTangentS.AsVector3D(), vecTangentT );
+
+ unsigned char red = (int)( u * 255.0f );
+ unsigned char green = (int)( v * 255.0f );
+ unsigned char blue = (int)( v * 255.0f );
+ unsigned char alpha = (int)( v * 255.0f );
+
+ vecPos += vCenter;
+
+ float u1, u2, v1, v2;
+ u1 = u2 = u;
+ v1 = v2 = v;
+
+ meshBuilder.Position3fv( vecPos.Base() );
+ meshBuilder.Normal3fv( vecNormal.Base() );
+ meshBuilder.Color4ub( red, green, blue, alpha );
+ meshBuilder.TexCoord2f( 0, u, v );
+ meshBuilder.TexCoord2f( 1, u1, v1 );
+ meshBuilder.TexCoord2f( 2, u2, v2 );
+ meshBuilder.TangentS3fv( vecTangentS.Base() );
+ meshBuilder.TangentT3fv( vecTangentT.Base() );
+ meshBuilder.BoneWeight( 0, 1.0f );
+ meshBuilder.BoneMatrix( 0, 0 );
+ meshBuilder.UserData( vecTangentS.Base() );
+ meshBuilder.AdvanceVertex();
+ }
+ }
+
+ //
+ // Emit the triangle strips.
+ //
+ int idx = 0;
+ for ( i = 0; i < nPhi - 1; ++i )
+ {
+ for ( j = 0; j < nTheta; ++j )
+ {
+ idx = nTheta * i + j;
+
+ meshBuilder.FastIndex( idx );
+ meshBuilder.FastIndex( idx + nTheta );
+ }
+
+ //
+ // Emit a degenerate triangle to skip to the next row without
+ // a connecting triangle.
+ //
+ if ( i < nPhi - 2 )
+ {
+ meshBuilder.FastIndex( idx + 1 );
+ meshBuilder.FastIndex( idx + 1 + nTheta );
+ }
+ }
+
+ meshBuilder.End();
+ pMesh->Draw();
+}
+
+
+//-----------------------------------------------------------------------------
+// Paints a regular texture
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::PaintStandardTexture( void )
+{
+ int x, y, w, h;
+ x = y = 0;
+ GetSize( w, h );
+ vgui::surface()->DrawSetTexture( m_nTextureID );
+ vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
+
+ // Get the aspect ratio of the texture
+ int tw = m_PreviewTexture->GetActualWidth();
+ int th = m_PreviewTexture->GetActualHeight();
+
+ if ( th > 0 && h > 0 )
+ {
+ float screenaspect = (float)tw / (float)th;
+ float aspect = (float)w / (float)h;
+
+ float ratio = screenaspect / aspect;
+
+ // Screen is wider, need bars at top and bottom
+ if ( ratio > 1.0f )
+ {
+ int usetall = (float)w / screenaspect;
+ y = ( h - usetall ) / 2;
+ h = usetall;
+ }
+ // Screen is narrower, need bars at left/right
+ else
+ {
+ int usewide = (float)h * screenaspect;
+ x = ( w - usewide ) / 2;
+ w = usewide;
+ }
+ }
+
+ vgui::surface()->DrawTexturedRect( x, y, x+w, y+h );
+}
+
+
+//-----------------------------------------------------------------------------
+// Paints a normalmap texture
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::PaintNormalMapTexture( void )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Paints a volume texture
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::PaintVolumeTexture( void )
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Paints a cubemap texture
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::PaintCubeTexture( void )
+{
+ float flNewTime = Plat_FloatTime();
+
+ // Circle the camera around the origin
+ VMatrix rot;
+ MatrixBuildRotateZ( rot, ROTATION_SPEED * (flNewTime - m_flLastRotationTime ) );
+ Vector vecTemp;
+ Vector3DMultiply( rot, m_vecCameraDirection, vecTemp );
+ m_vecCameraDirection = vecTemp;
+ m_flLastRotationTime = flNewTime;
+
+ LookAt( vec3_origin, 12.0f );
+
+ // Draw a sphere at the origin
+ RenderSphere( vec3_origin, 10.0f, 20, 20 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the camera to look at the the thing we're spinning around
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::LookAt( const Vector &vecLookAt, float flRadius )
+{
+ // Compute the distance to the camera for the object based on its
+ // radius and fov.
+
+ // since tan( fov/2 ) = f/d
+ // cos( fov/2 ) = r / r' where r = sphere radius, r' = perp distance from sphere center to max extent of camera
+ // d/f = r'/d' where d' is distance of camera to sphere
+ // d' = r' / tan( fov/2 ) * r' = r / ( cos (fov/2) * tan( fov/2 ) ) = r / sin( fov/2 )
+ float flFOVx = FOV;
+
+ // Compute fov/2 in radians
+ flFOVx *= M_PI / 360.0f;
+
+ // Compute an effective fov based on the aspect ratio
+ // if the height is smaller than the width
+ int w, h;
+ GetSize( w, h );
+ if ( h < w )
+ {
+ flFOVx = atan( h * tan( flFOVx ) / w );
+ }
+
+ float flDistance = flRadius / sin( flFOVx );
+
+ Vector vecMDLOrigin = vecLookAt;
+ Vector vecCameraOrigin;
+ VectorMA( vecMDLOrigin, -flDistance, m_vecCameraDirection, vecCameraOrigin );
+
+ CMatRenderContextPtr pRenderContext( MaterialSystem() );
+ QAngle angles;
+ VectorAngles( m_vecCameraDirection, angles );
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->LoadIdentity();
+
+ // convert from a right handed system to a left handed system
+ // since dx for wants it that way.
+// pRenderContext->Scale( 1.0f, 1.0f, -1.0f );
+
+ pRenderContext->Rotate( -90, 1, 0, 0 ); // put Z going up
+ pRenderContext->Rotate( 90, 0, 0, 1 ); // put Z going up
+ pRenderContext->Rotate( -angles[2], 1, 0, 0 );
+ pRenderContext->Rotate( -angles[0], 0, 1, 0 );
+ pRenderContext->Rotate( -angles[1], 0, 0, 1 );
+ pRenderContext->Translate( -vecCameraOrigin[0], -vecCameraOrigin[1], -vecCameraOrigin[2] );
+}
+
+
+//-----------------------------------------------------------------------------
+// Set up a projection matrix for a 90 degree fov
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::SetupProjectionMatrix( int nWidth, int nHeight )
+{
+ CMatRenderContextPtr pRenderContext( MaterialSystem() );
+ VMatrix proj;
+ float flFOV = FOV;
+ float flZNear = ZNEAR;
+ float flZFar = ZFAR;
+ float flApsectRatio = (nHeight != 0.0f) ? (float)nWidth / (float)nHeight : 100.0f;
+
+#if 1
+ float halfWidth = tan( flFOV * M_PI / 360.0 );
+ float halfHeight = halfWidth / flApsectRatio;
+#else
+ float halfHeight = tan( flFOV * M_PI / 360.0 );
+ float halfWidth = flApsectRatio * halfHeight;
+#endif
+ memset( proj.Base(), 0, sizeof( proj ) );
+ proj[0][0] = 1.0f / halfWidth;
+ proj[1][1] = 1.0f / halfHeight;
+ proj[2][2] = flZFar / ( flZNear - flZFar );
+ proj[3][2] = -1.0f;
+ proj[2][3] = flZNear * flZFar / ( flZNear - flZFar );
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->LoadMatrix( proj );
+}
+
+
+//-----------------------------------------------------------------------------
+// Paints the texture
+//-----------------------------------------------------------------------------
+void CVTFPreviewPanel::Paint( void )
+{
+ if ( !m_PreviewTexture->IsCubeMap() && /*!m_PreviewTexture->IsNormalMap() &&*/ !m_PreviewTexture->IsVolumeTexture() )
+ {
+ PaintStandardTexture();
+ return;
+ }
+
+ CMatRenderContextPtr pRenderContext( MaterialSystem() );
+ int w, h;
+ GetSize( w, h );
+ vgui::MatSystemSurface()->Begin3DPaint( 0, 0, w, h );
+
+ pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
+ pRenderContext->ClearBuffers( true, true );
+
+ SetupProjectionMatrix( w, h );
+
+ if ( m_PreviewTexture->IsCubeMap() )
+ {
+ PaintCubeTexture();
+ }
+ else if ( m_PreviewTexture->IsNormalMap() )
+ {
+ PaintNormalMapTexture();
+ }
+ else if ( m_PreviewTexture->IsVolumeTexture() )
+ {
+ PaintVolumeTexture();
+ }
+
+ vgui::MatSystemSurface()->End3DPaint( );
+} \ No newline at end of file