/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public IPickableRenderMethod ToRenderMethod(IBufferSource model) { // init shader program. ShaderProgram pickProgram = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. VertexBuffer positionBuffer = model.GetVertexAttributeBuffer(this.positionNameInIBufferSource); // RULE: 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 if (positionBuffer == null || positionBuffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } // init index buffer. IndexBuffer indexBuffer = model.GetIndexBuffer(); // init VAO. var pickingVAO = new VertexArrayObject(indexBuffer, pickProgram, new VertexShaderAttribute(positionBuffer, PickingShaderHelper.in_Position)); var renderUnit = new IPickableRenderMethod(pickProgram, pickingVAO, positionBuffer, this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. var ptr = indexBuffer as OneIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.ElementType); renderUnit.StateList.Add(glState); } return(renderUnit); }
/// <summary> /// /// </summary> protected override void DoInitialize() { base.DoInitialize(); IPickableRenderMethod renderUnit = this.pickingRenderUnitBuilder.ToRenderMethod(this.RenderUnit.Model); var pickerList = new List <PickerBase>(); foreach (var vao in renderUnit.VertexArrayObjects) { IDrawCommand cmd = vao.DrawCommand; if (cmd is DrawArraysCmd) //|| cmd is MultiDrawArraysCmd) { //I don't know what will happen during picking if 'overlap' exists in glMultiDrawArrays(..). I don't care either, because that is a problem that should be solved in modeling stage. VertexBuffer positionBuffer = vao.VertexAttributes[0].Buffer; // according to base.DoInitialize(), this is the position buffer of the only vertex attribute. pickerList.Add(new DrawArraysPicker(this, positionBuffer, cmd as DrawArraysCmd)); } else if (cmd is DrawElementsCmd) //|| cmd is MultiDrawElementsCmd) { //I don't know what will happen during picking if 'overlap' exists in glMultiDrawElements(..). I don't care either, because that is a problem that should be solved in modeling stage. VertexBuffer positionBuffer = vao.VertexAttributes[0].Buffer; // according to base.DoInitialize(), this is the position buffer of the only vertex attribute. pickerList.Add(new DrawElementsPicker(this, positionBuffer, cmd as DrawElementsCmd)); } else { throw new NotImplementedException(string.Format("`{0}` is a IDrawCommand type that has not been supported for `IPickable`.", cmd.GetType())); } } this.picker = pickerList.ToArray(); this.PickingRenderUnit = renderUnit; }
/// <summary> /// This method should only be invoked once. /// </summary> private void DoInitialize() { IBufferSource model = this.Model; for (int i = 0; i < this.builders.Length; i++) { IPickableRenderMethod method = this.builders[i].ToRenderMethod(model); this.Methods[i] = method; } }
/// <summary> /// /// </summary> protected override void DoInitialize() { base.DoInitialize(); { IPickableRenderMethod renderUnit = this.pickingRenderUnitBuilder.ToRenderMethod(this.RenderUnit.Model); if (renderUnit.VertexArrayObject.IndexBuffer is ZeroIndexBuffer) { this.picker = new ZeroIndexPicker(this); } else if (renderUnit.VertexArrayObject.IndexBuffer is OneIndexBuffer) { this.picker = new OneIndexPicker(this); } this.PickingRenderUnit = renderUnit; } }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public IPickableRenderMethod ToRenderMethod(IBufferSource model) { // init shader program. ShaderProgram pickProgram = this.programProvider.GetShaderProgram(); // init vertex attribute buffer objects. var positionBuffers = new List <VertexBuffer>(); // position attribute is divided into blocks. // we only care about the position attribute. foreach (var buffer in model.GetVertexAttributeBuffer(this.positionNameInIBufferSource)) { if (buffer == null) { throw new Exception(string.Format("[{0}] returns null buffer pointer!", model)); } positionBuffers.Add(buffer); } int blockCount = positionBuffers.Count; // RULE: 由于picking.vert/frag只支持vec3的position buffer,所以有此硬性规定。 foreach (var buffer in positionBuffers) { if (buffer == null || buffer.Config != VBOConfig.Vec3) { throw new Exception(string.Format("Position buffer must use a type composed of 3 float as PropertyBuffer<T>'s T!")); } } // init draw command. var allDrawCommands = (from item in model.GetDrawCommand() where (item != null) select item).ToArray(); int cmdCount = allDrawCommands.Length; if (cmdCount != blockCount) { throw new Exception("Draw Commands count != vertex buffer block count."); } // init VAO. var pickingVAOs = new VertexArrayObject[cmdCount]; for (int b = 0; b < cmdCount; b++) { var vertexAttributeBuffers = new VertexShaderAttribute(positionBuffers[b], PickingShaderHelper.in_Position); pickingVAOs[b] = new VertexArrayObject(allDrawCommands[b], pickProgram, vertexAttributeBuffers); } var renderUnit = new IPickableRenderMethod(pickProgram, pickingVAOs, positionBuffers.ToArray(), this.states); // RULE: Renderer takes uint.MaxValue, ushort.MaxValue or byte.MaxValue as PrimitiveRestartIndex. So take care this rule when designing a model's index buffer. foreach (var cmd in allDrawCommands) { var ptr = cmd as IHasIndexBuffer; if (ptr != null) { GLState glState = new PrimitiveRestartState(ptr.IndexBufferObject.ElementType); renderUnit.StateList.Add(glState); break; } } return(renderUnit); }