uiacceltk/hitchcock/coretoolkit/src/HuiMeshVisual.cpp
changeset 0 15bf7259bb7c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/src/HuiMeshVisual.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,318 @@
+/*
+* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   Implementation of CHuiMeshVisual. CHuiMeshVisual is a visual
+*                that is able to display a 3D triangle mesh.
+*
+*/
+
+
+
+#include "uiacceltk/HuiMeshVisual.h"
+#include "HuiRenderPlugin.h"
+#include "uiacceltk/HuiMesh.h" // only OpenGL ES supported
+#include "uiacceltk/huim3gmesh.h"
+#include "uiacceltk/huiproceduralmesh.h"
+#include "uiacceltk/HuiGc.h"
+#include "uiacceltk/HuiPanic.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiStatic.h"
+#include "uiacceltk/HuiEnv.h"
+#include "uiacceltk/HuiTexture.h"
+#include "uiacceltk/HuiControl.h"
+#include "uiacceltk/HuiVisual.h"
+
+EXPORT_C CHuiMeshVisual* CHuiMeshVisual::AddNewL(CHuiControl& aOwnerControl,
+												 THuiMeshType aMeshType,
+                                                 CHuiLayout* aParentLayout)
+    {
+    CHuiMeshVisual* mesh = STATIC_CAST(CHuiMeshVisual*,
+        aOwnerControl.AppendVisualL(EHuiVisualTypeMesh, aParentLayout));
+        
+	mesh->CreateMeshL(aMeshType);
+                
+    return mesh;
+    }
+
+
+CHuiMeshVisual::CHuiMeshVisual(MHuiVisualOwner& aOwner)
+        : CHuiVisual(aOwner)
+    {
+    }
+
+
+void CHuiMeshVisual::ConstructL()
+    {
+    CHuiVisual::ConstructL();
+    
+    CreateMeshL(EHuiMeshTypeProcedural);
+    
+    iSecondaryAlpha.SetStyle(EHuiTimedValueStyleLinear);
+
+    iScale.Set(1.f);
+
+    // Meshes use 3D projection by default.
+    SetFlag(EHuiVisualFlag3DProjection);
+    }
+
+
+CHuiMeshVisual::~CHuiMeshVisual()
+    {
+    }
+
+
+EXPORT_C void CHuiMeshVisual::CreateMeshL(THuiMeshType aMeshType)
+	{
+    // Create a new mesh.
+    iMesh.Set(CHuiMesh::NewL(aMeshType), EHuiHasOwnership);
+	}
+
+
+EXPORT_C void CHuiMeshVisual::SetImage(const THuiImage& aImage)
+    {
+    iImage = aImage;
+    }
+
+
+EXPORT_C void CHuiMeshVisual::SetSecondaryImage(const THuiImage& aImage)
+    {
+    iSecondaryImage = aImage;
+    SetChanged();
+    }
+
+
+EXPORT_C void CHuiMeshVisual::SetSpecularImage(const THuiImage& aImage)
+    {
+    if(iMesh->MeshType() == EHuiMeshTypeProcedural) 
+        {
+        CHuiProceduralMesh *mesh = static_cast<CHuiProceduralMesh*>(&iMesh.NonConstRef());
+        mesh->iMaterial.iSpecularImage = aImage;
+        SetChanged();
+        }
+    }
+
+
+void CHuiMeshVisual::SetPos( const THuiRealPoint& aPos, TInt aTransitionTime )
+	{
+	SetChanged(); // \todo optimize: do not set if the value is the same(?)
+	CHuiVisual::SetPos( aPos, aTransitionTime);
+	if ( iMesh->MeshType() == EHuiMeshTypeM3G )
+		{
+		// \todo Handle animation?
+		THuiRealPoint realSize = LocalPointInPixels(THuiRealPoint(Size().Target().iX,Size().Target().iY),EHuiReferenceStateTarget);
+		THuiRealRect rect( LocalPointInPixels(Pos().Target(),EHuiReferenceStateTarget), 
+							THuiRealSize(realSize.iX, realSize.iY) );
+		M3GMesh()->SetViewportRect( rect );
+		}
+	}
+
+
+void CHuiMeshVisual::SetSize( const THuiRealSize& aSize, TInt aTransitionTime )
+	{
+	SetChanged(); // \todo optimize: do not set if the value is the same(?)
+	CHuiVisual::SetSize( aSize, aTransitionTime);
+	if ( iMesh->MeshType() == EHuiMeshTypeM3G )
+		{
+		// \todo Handle animation
+		THuiRealPoint realSize = LocalPointInPixels(THuiRealPoint(Size().Target().iX,Size().Target().iY),EHuiReferenceStateTarget);
+		THuiRealRect rect( LocalPointInPixels(Pos().Target(),EHuiReferenceStateTarget), 
+							THuiRealSize(realSize.iX, realSize.iY) );
+		M3GMesh()->SetViewportRect( rect );
+		}
+	}
+
+
+void CHuiMeshVisual::SetRect( const THuiRealRect& aRect, TInt aTransitionTime )
+	{
+	SetChanged(); // \todo optimize: do not set if the value is the same(?)
+	CHuiVisual::SetRect( aRect, aTransitionTime );
+	if ( iMesh->MeshType() == EHuiMeshTypeM3G )
+		{
+		// \todo Handle animation
+		THuiRealPoint realSize = LocalPointInPixels(THuiRealPoint(Size().Target().iX,Size().Target().iY),EHuiReferenceStateTarget);
+		THuiRealRect rect( LocalPointInPixels(Pos().Target(),EHuiReferenceStateTarget), 
+							THuiRealSize(realSize.iX, realSize.iY) );
+		M3GMesh()->SetViewportRect( rect );
+		}
+	}
+
+
+void CHuiMeshVisual::DrawSelf(CHuiGc& aGc, const TRect& aDisplayRect) const
+    {
+    
+    THuiRealRect content = DisplayRect();
+    content.Shrink(PaddingInPixels(EHuiReferenceStateNow));
+    TReal32 opacity = EffectiveOpacity();
+
+    /*
+    aGc.SetProjection(CHuiGc::EProjectionPerspective);
+    if(Flags() & EHuiVisualFlagLocalHorizon)
+        {
+        aGc.SetFrustumOffset(content.Center());
+        }
+    */
+
+    aGc.SetPenColor(TRgb(255, 255, 255));
+    aGc.SetPenAlpha(TInt(255 * opacity));
+
+    aGc.Push(EHuiGcMatrixModel);
+
+    TReal32 scaling = 1.0f;
+
+    TReal32 yaw = iYawAngle.Now();
+    TReal32 pitch = iPitchAngle.Now();
+
+	CHuiProceduralMesh *proceduralMesh = ProceduralMesh();
+	CHuiM3GMesh *m3gMesh = M3GMesh();
+	if(proceduralMesh)
+		{
+		//translate
+	    THuiRealPoint mid = content.Center();
+	    aGc.Translate(EHuiGcMatrixModel, mid.iX, mid.iY, 0.f);
+	    
+	    // Scale the model based on the size (width) of the visual.
+	    /** @todo  Where does this factor really come from? () */
+    	scaling = .000113f * .2f * Min(content.Width(), content.Height()) * iScale.Now();
+    	aGc.Scale(EHuiGcMatrixModel, scaling, scaling, scaling);
+    	
+    	// Rotate
+		aGc.Rotate(EHuiGcMatrixModel, pitch, 1.f, 0.f, 0.f);		
+	    aGc.Rotate(EHuiGcMatrixModel, yaw, 0.f, 1.f, 0.f);  
+		}
+	if(m3gMesh)
+		{
+    	m3gMesh->SetViewportRect(aDisplayRect);
+    	
+		// translate
+	    THuiRealPoint tl = content.iTl;
+	    TRect dispArea = aGc.DisplayArea();
+	    // don't divide by 0
+	    if ( dispArea.Width() != 0 && dispArea.Height() != 0 )
+	        {
+	        aGc.Translate(EHuiGcMatrixModel, 2.f * (tl.iX / dispArea.Width()), -2.f * (tl.iY / dispArea.Height()), 0.f);
+	        }
+	    
+	    // scale
+	    scaling = iScale.Now();
+	    aGc.Scale(EHuiGcMatrixModel, scaling, scaling, scaling);
+	    
+	    // animate	    
+	    m3gMesh->AnimateControllers();
+	    
+    	m3gMesh->StoreCamera();
+    	
+    	// rotate    
+    	m3gMesh->RotateYaw(yaw);
+    	m3gMesh->RotatePitch(pitch);
+    	
+		}
+				
+    // Generate texture coordinates. Use NonConstRef() to get a modifiable
+    // reference to the mesh instance even though we are currently in
+    // a const method.
+    
+    if(proceduralMesh) 
+    	{
+    	proceduralMesh->UpdateSurface(yaw, pitch);
+
+
+        if(proceduralMesh->iMaterial.iPreset == EHuiMaterialShadow)
+            {
+            // Set up a shadow projection.
+            /** @todo  Should determine max Z of model and project there. */
+            TReal32 mat[16];
+            TReal32 point[3] =
+                {
+                0, 0, -18000
+                };
+            TReal32 normal[3] =
+                {
+                0, 0, 1
+                };
+            TReal32 light[4] =
+                {
+                -750, -750, 1000, 0
+                };
+            HuiUtil::ShadowMatrix(point, normal, light, mat);
+            aGc.Multiply(EHuiGcMatrixModel, mat);
+            }
+
+    	}
+	
+    // Depth testing is needed when drawing in 3D.
+    /** @todo  Push attrib needed for depth test. */
+    aGc.Enable(CHuiGc::EFeatureDepthTest);
+    aGc.DrawMesh(iMesh.Ref(), &iImage, &iSecondaryImage, iSecondaryAlpha.Now());
+    aGc.Disable(CHuiGc::EFeatureDepthTest);
+
+	if (m3gMesh) 
+		{
+		m3gMesh->RestoreCamera();
+		}
+
+    // Restore original transformation.
+    aGc.Pop(EHuiGcMatrixModel);
+    }
+
+TBool CHuiMeshVisual::Changed() const
+    {
+    if(CHuiVisual::Changed())
+        {
+        return ETrue;
+        }
+    return iYawAngle.Changed() || iPitchAngle.Changed() || iScale.Changed() || iImage.Changed() || iSecondaryImage.Changed();
+    }
+
+
+void CHuiMeshVisual::ClearChanged()
+    {
+    CHuiVisual::ClearChanged();
+    iYawAngle.ClearChanged();
+    iPitchAngle.ClearChanged();
+    iImage.ClearChanged();
+    iSecondaryImage.ClearChanged();
+    }
+
+
+EXPORT_C CHuiMesh& CHuiMeshVisual::Mesh()
+    {
+    SetChanged(); // \todo Why this is always set?
+    return iMesh.Ref();
+    }
+
+// ---------------------------------------------------------------------------
+// Return procedural mesh
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CHuiProceduralMesh* CHuiMeshVisual::ProceduralMesh() const
+	{
+	if(iMesh->MeshType() != EHuiMeshTypeProcedural) 
+		{
+		return NULL;
+		}    
+	return (CHuiProceduralMesh*)(&iMesh.Ref());
+	}
+
+// ---------------------------------------------------------------------------
+// Return M3G mesh
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CHuiM3GMesh* CHuiMeshVisual::M3GMesh() const 
+	{
+	if(iMesh->MeshType() != EHuiMeshTypeM3G) 
+		{
+		return NULL;
+		}    
+	return (CHuiM3GMesh*)(&iMesh.Ref());
+	}
+