Преглед на файлове

created INode.Clone(), and added ModelMatrix uniform to Graphic

Daniel Salvadori преди 7 години
родител
ревизия
f2f1bf0213
променени са 3 файла, в които са добавени 101 реда и са изтрити 5 реда
  1. 37 0
      core/node.go
  2. 40 4
      graphic/graphic.go
  3. 24 1
      graphic/mesh.go

+ 37 - 0
core/node.go

@@ -18,6 +18,7 @@ type INode interface {
 	Raycast(*Raycaster, *[]Intersect)
 	BoundingBox() math32.Box3
 	Render(gs *gls.GLS)
+	Clone() INode
 	Dispose()
 }
 
@@ -100,6 +101,42 @@ func (n *Node) Render(gs *gls.GLS) {
 func (n *Node) Dispose() {
 }
 
+// Clone clones the Node and satisfies the INode interface.
+func (n *Node) Clone() INode {
+
+	clone := new(Node)
+
+	// TODO clone Dispatcher?
+	clone.Dispatcher.Initialize()
+
+	clone.parent = n.parent
+	clone.name = n.name + " (Clone)" // TODO append count?
+	clone.loaderID = n.loaderID
+	clone.visible = n.visible
+	clone.userData = n.userData
+
+	// Update matrix world and rotation if necessary
+	n.UpdateMatrixWorld()
+	n.Rotation()
+
+	// Clone spatial properties
+	clone.position = n.position
+	clone.scale = n.scale
+	clone.direction = n.direction
+	clone.rotation = n.rotation
+	clone.quaternion = n.quaternion
+	clone.matrix = n.matrix
+	clone.matrixWorld = n.matrixWorld
+	clone.children = make([]INode, 0)
+
+	// Clone children recursively
+	for _, child := range n.children {
+		clone.Add(child.Clone())
+	}
+
+	return clone
+}
+
 // SetParent sets the parent.
 func (n *Node) SetParent(iparent INode) {
 

+ 40 - 4
graphic/graphic.go

@@ -27,6 +27,7 @@ type Graphic struct {
 
 	ShaderDefines gls.ShaderDefines // Graphic-specific shader defines
 
+	mm   math32.Matrix4 // Cached Model matrix
 	mvm  math32.Matrix4 // Cached ModelView matrix
 	mvpm math32.Matrix4 // Cached ModelViewProjection matrix
 }
@@ -107,6 +108,29 @@ func (gr *Graphic) Dispose() {
 	}
 }
 
+// Clone clones the graphic and satisfies the INode interface.
+// It should be called by Clone() implementations of IGraphic.
+// Note that the topmost implementation calling this method needs
+// to call clone.SetIGraphic(igraphic) after calling this method.
+func (gr *Graphic) Clone() core.INode {
+
+	clone := new(Graphic)
+	clone.Node = *gr.Node.Clone().(*core.Node)
+	clone.igeom = gr.igeom
+	clone.mode = gr.mode
+	clone.renderable = gr.renderable
+	clone.cullable = gr.cullable
+	clone.renderOrder = gr.renderOrder
+	clone.ShaderDefines = gr.ShaderDefines
+	clone.materials = make([]GraphicMaterial, len(gr.materials))
+
+	for _, grmat := range gr.materials {
+		clone.materials = append(clone.materials, grmat)
+	}
+
+	return clone
+}
+
 // SetRenderable satisfies the IGraphic interface and
 // sets the renderable state of this Graphic (default = true).
 func (gr *Graphic) SetRenderable(state bool) {
@@ -195,11 +219,17 @@ func (gr *Graphic) GetMaterial(vpos int) material.IMaterial {
 	return nil
 }
 
+// ClearMaterials removes all the materials from this Graphic.
+func (gr *Graphic) ClearMaterials() {
+
+	gr.materials = gr.materials[0:0]
+}
+
 // SetIGraphic sets the IGraphic on all this Graphic's GraphicMaterials.
-func (gr *Graphic) SetIGraphic(ig IGraphic) {
+func (gr *Graphic) SetIGraphic(igr IGraphic) {
 
 	for i := range gr.materials {
-		gr.materials[i].igraphic = ig
+		gr.materials[i].igraphic = igr
 	}
 }
 
@@ -222,11 +252,17 @@ func (gr *Graphic) BoundingBox() math32.Box3 {
 // CalculateMatrices calculates the model view and model view projection matrices.
 func (gr *Graphic) CalculateMatrices(gs *gls.GLS, rinfo *core.RenderInfo) {
 
-	mw := gr.MatrixWorld()
-	gr.mvm.MultiplyMatrices(&rinfo.ViewMatrix, &mw)
+	gr.mm = gr.MatrixWorld()
+	gr.mvm.MultiplyMatrices(&rinfo.ViewMatrix, &gr.mm)
 	gr.mvpm.MultiplyMatrices(&rinfo.ProjMatrix, &gr.mvm)
 }
 
+// ModelViewMatrix returns the last cached model view matrix for this graphic.
+func (gr *Graphic) ModelMatrix() *math32.Matrix4 {
+
+	return &gr.mm
+}
+
 // ModelViewMatrix returns the last cached model view matrix for this graphic.
 func (gr *Graphic) ModelViewMatrix() *math32.Matrix4 {
 

+ 24 - 1
graphic/mesh.go

@@ -15,6 +15,7 @@ import (
 // Mesh is a Graphic with uniforms for the model, view, projection, and normal matrices.
 type Mesh struct {
 	Graphic             // Embedded graphic
+	uniMm  gls.Uniform  // Model matrix uniform location cache
 	uniMVm  gls.Uniform // Model view matrix uniform location cache
 	uniMVPm gls.Uniform // Model view projection matrix uniform cache
 	uniNm   gls.Uniform // Normal matrix uniform cache
@@ -36,6 +37,7 @@ func (m *Mesh) Init(igeom geometry.IGeometry, imat material.IMaterial) {
 	m.Graphic.Init(igeom, gls.TRIANGLES)
 
 	// Initialize uniforms
+	m.uniMm.Init("ModelMatrix")
 	m.uniMVm.Init("ModelViewMatrix")
 	m.uniMVPm.Init("MVP")
 	m.uniNm.Init("NormalMatrix")
@@ -58,14 +60,35 @@ func (m *Mesh) AddGroupMaterial(imat material.IMaterial, gindex int) {
 	m.Graphic.AddGroupMaterial(m, imat, gindex)
 }
 
+// Clone clones the mesh and satisfies the INode interface.
+func (m *Mesh) Clone() core.INode {
+
+	clone := new(Mesh)
+	clone.Graphic = *m.Graphic.Clone().(*Graphic)
+	clone.SetIGraphic(clone)
+
+	// Initialize uniforms
+	clone.uniMm.Init("ModelMatrix")
+	clone.uniMVm.Init("ModelViewMatrix")
+	clone.uniMVPm.Init("MVP")
+	clone.uniNm.Init("NormalMatrix")
+
+	return clone
+}
+
 // RenderSetup is called by the engine before drawing the mesh geometry
 // It is responsible to updating the current shader uniforms with
 // the model matrices.
 func (m *Mesh) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
 
+	// Transfer uniform for model matrix
+	mm := m.ModelMatrix()
+	location := m.uniMm.Location(gs)
+	gs.UniformMatrix4fv(location, 1, false, &mm[0])
+
 	// Transfer uniform for model view matrix
 	mvm := m.ModelViewMatrix()
-	location := m.uniMVm.Location(gs)
+	location = m.uniMVm.Location(gs)
 	gs.UniformMatrix4fv(location, 1, false, &mvm[0])
 
 	// Transfer uniform for model view projection matrix