//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ protected override void BindParent() { /*geomerty nodes*/ _mechNode = this.Parent.FindChild("mech", true); _headNode = this.Parent.FindChild("head", true); _bodyNode = this.Parent.FindChild("body", true); _ulegLeftNode = _bodyNode.FindChild("ulegl", true); _ulegRightNode = _bodyNode.FindChild("ulegr", true); _llegLeftNode = _ulegLeftNode.FindChild("llegl", true); _llegRightNode = _ulegRightNode.FindChild("llegr", true); _footLeftNode = _llegLeftNode.FindChild("footl", true); _footRightNode = _llegRightNode.FindChild("footr", true); /*animation*/ this._animation.Animations.Add(_bodyNode.Animation); this._animation.Animations.Add(_ulegLeftNode.Animation); this._animation.Animations.Add(_ulegRightNode.Animation); this._animation.Animations.Add(_llegLeftNode.Animation); this._animation.Animations.Add(_llegRightNode.Animation); this._animation.Animations.Add(_footLeftNode.Animation); this._animation.Animations.Add(_footRightNode.Animation); this._animation.SetRange(0, 48, true); /*collision*/ Node coll = _mechNode.FindChild("__cs_mech", true); this._collision = (CollisionComponent) coll.Components[Component.CollisionComponent]; }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public bool Test(CullInfo cullInfo, Node node, MeshItem meshItem) { float x = meshItem.BoundingVolume.Center.Elements[0]; float y = meshItem.BoundingVolume.Center.Elements[1]; float z = meshItem.BoundingVolume.Center.Elements[2]; /*First: we transform our coordinate into eye coordinates from model-view.*/ float xp = x * cullInfo.ModelView[0] + y * cullInfo.ModelView[4] + z * cullInfo.ModelView[8] + cullInfo.ModelView[12]; float yp = x * cullInfo.ModelView[1] + y * cullInfo.ModelView[5] + z * cullInfo.ModelView[9] + cullInfo.ModelView[13]; float zp = x * cullInfo.ModelView[2] + y * cullInfo.ModelView[6] + z * cullInfo.ModelView[10] + cullInfo.ModelView[14]; /*then we transform the furthest away vertex to mv to comute sphere radius*/ float xv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3]; float yv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3 + 1]; float zv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3 + 2]; float xpv = xv * cullInfo.ModelView[0] + yv * cullInfo.ModelView[4] + zv * cullInfo.ModelView[8] + cullInfo.ModelView[12]; float ypv = xv * cullInfo.ModelView[1] + yv * cullInfo.ModelView[5] + zv * cullInfo.ModelView[9] + cullInfo.ModelView[13]; float zpv = xv * cullInfo.ModelView[2] + yv * cullInfo.ModelView[6] + zv * cullInfo.ModelView[10] + cullInfo.ModelView[14]; /*now we compute the radius*/ float r = Math.Sqrt((xp - xpv) * (xp - xpv) + (yp - ypv) * (yp - ypv) + (zp - zpv) * (zp - zpv)); if (xp + r < -this._regionX) return false; if (xp - r > this._regionX) return false; if (yp + r < -this._regionY) return false; if (yp - r > this._regionY) return false; return true; }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ protected override void BindParent() { this._cameraNode = Parent; /*initial position*/ this._cameraNode.Translate3(0.0f, 30.0f, 17.0f); this._cameraNode.RotateX(-1.0f); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public void RemoveNode(Node node) { if(node == null) return; this._rootNodes.Remove(node); this.NodeRemoved.Fire(this, node); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public void AddRootNode(Node node) { if(node == null) throw new Exception("Node cannot be null."); this._rootNodes.Add(node); this.NodeAdded.Fire(this, node); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public bool Test(CullInfo cullInfo, Node node, MeshItem meshItem) { float x = meshItem.BoundingVolume.Center.Elements[0]; float y = meshItem.BoundingVolume.Center.Elements[1]; float z = meshItem.BoundingVolume.Center.Elements[2]; /*First: we transform our coordinate into eye coordinates from model-view.*/ float xp = x * cullInfo.ModelView[0] + y * cullInfo.ModelView[4] + z * cullInfo.ModelView[8] + cullInfo.ModelView[12]; float yp = x * cullInfo.ModelView[1] + y * cullInfo.ModelView[5] + z * cullInfo.ModelView[9] + cullInfo.ModelView[13]; float zp = x * cullInfo.ModelView[2] + y * cullInfo.ModelView[6] + z * cullInfo.ModelView[10] + cullInfo.ModelView[14]; /*then we transform the furthest away vertex to mv to comute sphere radius*/ float xv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3]; float yv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3 + 1]; float zv = meshItem.Mesh[meshItem.BoundingVolume.VertexIndex * 3 + 2]; float xpv = xv * cullInfo.ModelView[0] + yv * cullInfo.ModelView[4] + zv * cullInfo.ModelView[8] + cullInfo.ModelView[12]; float ypv = xv * cullInfo.ModelView[1] + yv * cullInfo.ModelView[5] + zv * cullInfo.ModelView[9] + cullInfo.ModelView[13]; float zpv = xv * cullInfo.ModelView[2] + yv * cullInfo.ModelView[6] + zv * cullInfo.ModelView[10] + cullInfo.ModelView[14]; /*now we compute the radius*/ float r = Math.Sqrt((xp - xpv) * (xp - xpv) + (yp - ypv) * (yp - ypv) + (zp - zpv) * (zp - zpv)); /*Now - we apply the "plane equation" of each clip plane to see how far from the clip plane our point is. The clip planes are directed: positive number distances mean we are INSIDE our viewing area by some distance; negative means outside. So ... if we are outside by less than -r, the ENTIRE sphere is out of bounds. We are not visible! We do the near clip plane, then sides, then far, in an attempt to try the planes that will eliminate the most geometry first...half the world is behind the near clip plane, but not much is behind the far clip plane on sunny day.*/ if ((xp * cullInfo.NearClip [0] + yp * cullInfo.NearClip [1] + zp * cullInfo.NearClip [2] + cullInfo.NearClip [3] + r) < 0) return false; if ((xp * cullInfo.BotClip [0] + yp * cullInfo.BotClip [1] + zp * cullInfo.BotClip [2] + cullInfo.BotClip [3] + r) < 0) return false; if ((xp * cullInfo.TopClip [0] + yp * cullInfo.TopClip [1] + zp * cullInfo.TopClip [2] + cullInfo.TopClip [3] + r) < 0) return false; if ((xp * cullInfo.LeftClip [0] + yp * cullInfo.LeftClip [1] + zp * cullInfo.LeftClip [2] + cullInfo.LeftClip [3] + r) < 0) return false; if ((xp * cullInfo.RightClip[0] + yp * cullInfo.RightClip[1] + zp * cullInfo.RightClip[2] + cullInfo.RightClip[3] + r) < 0) return false; if ((xp * cullInfo.FarClip [0] + yp * cullInfo.FarClip [1] + zp * cullInfo.FarClip [2] + cullInfo.FarClip [3] + r) < 0) return false; return true; }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ private void InitializeCollision(Node node) { CollisionComponent component = (CollisionComponent) node.Components[Component.CollisionComponent]; if(component.Body != null) this.DestroyCollision(node); component.Body = this._b2World.CreateBody(component.BodyDefinition); component.Body.CreateFixture(component.FixtureDefinition); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ private void DestroyCollision(Node node) { CollisionComponent component = (CollisionComponent)node.Components[Component.CollisionComponent]; if(component.Body == null) return; this._b2World.DestroyBody(component.Body); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public Boolean RemoveChild(Node child) { if (this.Children[child.Id] == null) return false; this.Children.Remove(child.Id); this.ChildrenList.Remove(child); child.Parent = null; this.ChildRemoved.Fire(this, child); return true; }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public void AddChild(Node child) { if (this.Children[child.Id] != null) throw new Exception("Child with the same name already exists."); this.Children[child.Id] = child; this.ChildrenList.Add(child); child.Parent = this; this.ChildAdded.Fire(this, child); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public void Bind(Node parent) { this.Parent = parent; this.BindParent(); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ private void RenderOpaqueMesh(Node node, Matrix4X4 mv, Matrix4X4 nv, int vertexLength, IShaderBinder binder) { /*check for material*/ MaterialComponent materialComponent = (MaterialComponent)node.Components[Component.MaterialComponent]; if (materialComponent == null) { this.DebugLog("Cannot render node [" + node.Id + "] : material not found."); return; } /*get the actual objects*/ MaterialItem material = (MaterialItem)this.Library.GetResource(materialComponent.MaterialHandle); binder.BindGeometryMaterial(material); binder.BindGeometryInstance(mv, nv); /*due to the lack of mrt support, I have to use multiple passes for the same object*/ /*diffuse pass*/ this.SwitchRenderGroup(this._diffuseGroup); this._context.DepthFunc(WebGLE.Lequal); binder.BindGeometryPassNum(0); this._context.DrawElements(WebGLE.Triangles, vertexLength, WebGLE.UnsignedShortT, 0); /*position pass*/ this.SwitchRenderGroup(this._positionGroup); this._context.DepthFunc(WebGLE.Equal); binder.BindGeometryPassNum(1); this._context.DrawElements(WebGLE.Triangles, vertexLength, WebGLE.UnsignedShortT, 0); /*normal pass*/ this.SwitchRenderGroup(this._normalGroup); binder.BindGeometryPassNum(2); this._context.DrawElements(WebGLE.Triangles, vertexLength, WebGLE.UnsignedShortT, 0); }
//------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ public void Initialize(float fov, float zNear, float zFar) { this.DisplayDebugInformation(); WebGLGraphics that = this; /*render texture dimensions*/ this._renderTextureDim = this.SmallestPowerOfTwo(_canvas.Width); this._renderViewport = SystemCore.Environment.CreateFloat32ArrayFromArray(new float[] { _renderTextureDim, _renderTextureDim, }); this._shaderGroups = new Dictionary<string, ShaderGroup>(); /*rendering shaders*/ ShaderGroup phongShaderGroup = new ShaderGroup(); phongShaderGroup.Name = "phong"; phongShaderGroup.ShaderBinder = new PhongBinder(that.Library, that._context, phongShaderGroup); SystemCore.ResourceManager.GetResource("/Data/Shader/phong_pass_geom.shader", null).ResourceChanged.Subscribe( delegate(object sender, object args) { Resource resource = (Resource) sender; if (resource.Finished) { phongShaderGroup.GeometryPassShader = (CompiledShader) resource.Data; } }, null); SystemCore.ResourceManager.GetResource("/Data/Shader/phong_pass_prepost.shader", null).ResourceChanged.Subscribe( delegate(object sender, object args) { Resource resource = (Resource)sender; if (resource.Finished) { phongShaderGroup.PrePostProcessPassShader = (CompiledShader)resource.Data; } }, null); SystemCore.ResourceManager.GetResource("/Data/Shader/phong_pass_light.shader", null).ResourceChanged.Subscribe( delegate(object sender, object args) { Resource resource = (Resource)sender; if (resource.Finished) { phongShaderGroup.LightPassShader = (CompiledShader)resource.Data; } }, null); SystemCore.ResourceManager.GetResource("/Data/Shader/phong_pass_final.shader", null).ResourceChanged.Subscribe( delegate(object sender, object args) { Resource resource = (Resource)sender; if (resource.Finished) { phongShaderGroup.FinalPassShader = (CompiledShader)resource.Data; } }, null); this.AddShaderGroup(phongShaderGroup); this.ActiveShaderGroup = "phong"; /*core library - which contain things like light bounding meshes*/ Library.LoadLibrary("/Data/JSON/core.json").Finished.Subscribe(delegate(object sender, object args) { Handle sphereHandle = new Handle(); sphereHandle.Collection = "core"; sphereHandle.Id = "point_light_sphere-lib"; that._lightSphereVolume = ((MeshItem)Library.GetResource(sphereHandle)); }, true); /*enable webGL float texture extension*/ SystemCore.Logger.Log(this._context.GetExtension("OES_texture_float").ToString()); this.SetupFrameBuffers(); /*webgl render queues*/ this._opaqueMeshQueue = new List<List<Node>>(); this._transparentMeshQueue = new List<List<Node>>(); this._lightQueue = new Dictionary<int, List<Node>>(); /*camera*/ this._camera = new Node(); this._camera.AddComponent(new CameraComponent()); /*perspective*/ this._scaleMatrix = new Matrix4X4(null); this._mvMatrix = new Matrix4X4(null); this._vMatrix = new Matrix4X4(null); this._nMatrix = new Matrix4X4(null); this._pMatrix = Matrix4X4.MakePerspective(fov, 800.0f / 600.0f, zNear, zFar); this._context.Viewport(0, 0, this._renderTextureDim, this._renderTextureDim); this._context.EnableVertexAttribArray(0); this._context.EnableVertexAttribArray(1); this._context.EnableVertexAttribArray(2); this._context.Enable(WebGLE.DepthTest); this._context.Enable(WebGLE.CullFace); this._context.BlendFunc(WebGLE.SrcAlpha, WebGLE.One); /*occlusion*/ this._cullInfo = new CullInfo(); /*post process effects*/ this._effects = new List<IPostProcessEffect>(); /*active texture targets*/ this._activeTextureTarget = new List<int>(); this._activeTextureTarget[0] = WebGLE.Texture0; this._activeTextureTarget[1] = WebGLE.Texture1; this._activeTextureTarget[2] = WebGLE.Texture2; /*I don't need any more for now*/ }