Public MustInherit Class ModelWorldObject
    Inherits WorldObject

    Protected _SupressLoadContent As Boolean = False
    Private _Scale As Vector3 = New Vector3(1)

    Public Property Model As Microsoft.Xna.Framework.Graphics.Model
    Public Property ModelName As String


    Public Property Scale As Vector3
        Get
            Return Me._Scale
        End Get
        Set(value As Vector3)
            Me._Scale = value
            Me.OnScaleChanged()
        End Set
    End Property

    Public Sub OnScaleChanged()
        Me.UpdateBoundingObjects()
    End Sub

    Sub New(game As Game, world As VirtualWorld, position As Vector3, rotation As Vector3, scale As Vector3, modelName As String)
        MyBase.New(game, world, position, rotation)
        Me.ModelName = modelName
        'we always want to generate the bounding sphere first
        Me.UpdateBoundingBoxFirst = False
        Me._Scale = scale
    End Sub

    Sub New(game As Game, world As VirtualWorld, position As Vector3, rotation As Vector3, scale As Vector3, model As Model)
        MyBase.New(game, world, position, rotation)
        Me.Model = model
        Me.UpdateBoundingBoxFirst = False
        Me._Scale = scale
    End Sub

    Public Overrides ReadOnly Property Size As Microsoft.Xna.Framework.Vector3
        Get
            With Me.BoundingBox
                Return New Vector3(.Max.X - .Min.X, .Max.Y - .Min.Y, .Max.Z - .Min.Z)
            End With
        End Get
    End Property

    Protected Overrides Sub LoadContent()
        If Me._SupressLoadContent Then Exit Sub
        If Me.Model Is Nothing Then
            If String.IsNullOrEmpty(Me.ModelName) = False Then
                Me.Model = Me.Game.Content.Load(Of Model)(Me.ModelName)
                Me.UpdateBoundingObjects()
            End If
        End If
        MyBase.LoadContent()
    End Sub

    Public Sub Load()
        Me.LoadContent()
        Me._SupressLoadContent = True
    End Sub

    Public Overrides Sub Draw(gameTime As Microsoft.Xna.Framework.GameTime)
        Dim transforms(Me.Model.Bones.Count) As Matrix
        Me.Model.CopyAbsoluteBoneTransformsTo(transforms)
        Dim worldMatrix As Matrix = Matrix.Identity
        Dim translateMatrix As Matrix = Matrix.CreateTranslation(Me.Position)
        Dim scaleMatrix As Matrix = Matrix.CreateScale(Me.Scale)
        Dim rotationMatrixX As Matrix = Matrix.CreateRotationX(MathHelper.ToRadians(Me.Rotation.X))
        Dim rotationMatrixY As Matrix = Matrix.CreateRotationY(MathHelper.ToRadians(Me.Rotation.Y))
        Dim rotationMatrixZ As Matrix = Matrix.CreateRotationZ(MathHelper.ToRadians(Me.Rotation.Z))
        worldMatrix = scaleMatrix * rotationMatrixX * rotationMatrixY * rotationMatrixZ * translateMatrix
        Me.BeginDraw(Me.World.ViewMatrix, Me.World.ProjectionMatrix, Me.GraphicsDevice, Me.World.Effect)
        For Each mesh As ModelMesh In Model.Meshes
            For Each e As BasicEffect In mesh.Effects
                e.World = transforms(mesh.ParentBone.Index) * worldMatrix
                e.View = Me.World.ViewMatrix
                e.Projection = Me.World.ProjectionMatrix
                e.TextureEnabled = True
                e.EnableDefaultLighting()
                e.PreferPerPixelLighting = True
            Next
            mesh.Draw()
        Next
        Me.EndDraw(Me.World.ViewMatrix, Me.World.ProjectionMatrix, Me.GraphicsDevice, Me.World.Effect)
    End Sub

    Protected Friend Overrides Sub UpdateBoundingBox()
        Me._BoundingBox = BoundingBox.CreateFromSphere(Me.BoundingSphere)
        Me.OnBoundingBoxUpdated()
    End Sub

    Protected Friend Overrides Sub UpdateBoundingSphere()
        Dim mergedSphere As New BoundingSphere

        Dim index As Integer = 0
        Dim meshCount As Integer = Model.Meshes.Count
        Dim boundingSpheres(meshCount) As BoundingSphere
        For Each mesh As ModelMesh In Me.Model.Meshes
            boundingSpheres(index) = mesh.BoundingSphere
            index += 1
        Next
        mergedSphere = boundingSpheres(0)
        If Model.Meshes.Count > 1 Then
            index = 1
            Do
                mergedSphere = BoundingSphere.CreateMerged(mergedSphere, boundingSpheres(index))
                index += 1
            Loop While (index < Model.Meshes.Count)
        End If
        mergedSphere.Center = Me.Position
        Me._BoundingSphere = mergedSphere
        Me.OnBoundingSphereUpdated()
    End Sub

    Protected Overridable Sub OnBoundingSphereUpdated()

    End Sub

    Protected Overridable Sub OnBoundingBoxUpdated()

    End Sub
End Class
