예제 #1
0
 private CameraHelper(Camera camera, Geometry geometry, LineBasicMaterial material)
     : base(geometry, material, LineType.Pieces)
 {
     this.camera = camera;
     this.matrixWorld = camera.matrixWorld;
     this.matrixAutoUpdate = false;
 }
예제 #2
0
 public static Vector3 ProjectVector(Vector3 vector, Camera camera)
 {
     camera.matrixWorldInverse = Matrix4.GetInverse(camera.matrixWorld);
     viewProjectionMatrix.MultiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
     var v = vector;
     v.ApplyProjection(viewProjectionMatrix);
     return v;
 }
예제 #3
0
        public static Raycaster PickingRay(Vector3 vector, Camera camera)
        {
            // set two vectors with opposing z values
            vector.z = -1;
            var end = new Vector3(vector.x, vector.y, 1);
            var start = UnprojectVector(vector, camera.projectionMatrix, camera.matrixWorld);
            end = UnprojectVector(end, camera.projectionMatrix, camera.matrixWorld);

            // find direction from vector to end
            end.Subtract(start);
            end.Normalize();
            return new Raycaster(start, end);
        }
예제 #4
0
        private void Update(Scene scene, Camera camera)
        {
            // set GL state for depth map
		    GL.ClearColor( 1, 1, 1, 1 );
		    GL.Disable( EnableCap.Blend);
            renderer.DepthTest = true;

		// update scene
		if ( scene.AutoUpdate) scene.UpdateMatrixWorld();

		// update camera matrices and frustum
		camera.matrixWorldInverse = Matrix4.GetInverse(camera.matrixWorld);
            projectionScreenMatrix.MultiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
		frustum = Frustum.FromMatrix( projectionScreenMatrix );

		// render depth map
            renderer.SetRenderTarget(renderTarget );
		renderer.Clear();

		// set object matrices & frustum culling
		renderList.Clear();
		ProjectObject(scene,scene,camera);

		// render regular objects
            foreach(var glObject in renderList) 
            {
			var o = glObject.Object;
			var buffer = glObject.Buffer;

			// TODO: create proper depth material for particles
			if(o is PointCloud /*&& !o.customDepthMaterial*/) continue;

           // var useMorphing = o.geometry.MorphTargets != null && o.geometry.MorphTargets.Count > 0; /* TODO IAN, need this for skinning? && object.Material.morphTargets */
           //     var useSkinning = o is SkinnedMesh; /* TODO IAN, need this for skinning? && object.Material.skinning */

                Material material;
			if (o.customDepthMaterial != null) material = o.customDepthMaterial;
			//else if ( useSkinning ) material = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin;
            //else if ( useMorphing ) material = depthMaterialMorph;
            else material = depthMaterial;
                
			renderer.RenderBuffer( camera, scene.lights, null, material, buffer, o );
		}

		// restore GL state
		var clearColor = renderer.ClearColor;
            GL.ClearColor(clearColor.R, clearColor.G, clearColor.B, 1 );
            GL.Enable( EnableCap.Blend);
        }
예제 #5
0
        private void Update(Scene scene, Camera camera)
        {
            // set GL state for depth map
            GL.ClearColor(1, 1, 1, 1);
            GL.Disable(EnableCap.Blend);
            GL.Enable(EnableCap.CullFace);
            GL.FrontFace(FrontFaceDirection.Ccw);

            GL.CullFace(renderer.shadowMapCullFace);

            renderer.DepthTest = true;
            var lights = new List<Light>();

            // preprocess lights
            // 	- skip lights that are not casting shadows
            //	- create virtual lights for cascaded shadow maps
            foreach (var light in scene.lights)
            {
                if (!light.DoesCastShadow) continue;

                var shadowLight = light as HasShadow;
                if (shadowLight != null && shadowLight.ShadowCascade)
                {
                    for (var n = 0; n < shadowLight.ShadowCascadeCount; n++)
                    {
                        VirtualLight virtualLight;

                        if (shadowLight.ShadowCascadeArray[n] == null)
                        {
                            virtualLight = CreateVirtualLight(light, n);
                            virtualLight.OriginalCamera = camera;

                            var gyro = new Gyroscope();
                            gyro.Position = shadowLight.ShadowCascadeOffset;

                            gyro.Add(virtualLight);
                            //gyro.Add(virtualLight.Target);
                            camera.Add(gyro);

                            shadowLight.ShadowCascadeArray[n] = virtualLight;
                            Debug.WriteLine("Created virtualLight {0}", virtualLight);
                        }
                        else
                        {
                            virtualLight = shadowLight.ShadowCascadeArray[n];
                        }

                        UpdateVirtualLight(light, n);
                        lights.Add(virtualLight);
                    }
                }
                else
                {
                    lights.Add(light);
                }

            }

            // render depth map
            foreach (var light in lights)
            {
                var hasShadow = light as HasShadow;
                if (hasShadow.shadowMap == null)
                {
                    var isSoftShadow = renderer.shadowMapType == ShadowType.PCFSoftShadowMap;
                    hasShadow.shadowMap = new RenderTarget(hasShadow.ShadowMapWidth, hasShadow.ShadowMapHeight);
                    hasShadow.shadowMap.MinFilter = isSoftShadow ? TextureMinFilter.Nearest : TextureMinFilter.Linear;
                    hasShadow.shadowMap.MagFilter = isSoftShadow ? TextureMagFilter.Nearest : TextureMagFilter.Linear; ;
                    hasShadow.shadowMap.Format = Three.Net.Renderers.PixelFormat.RGBA;

                    hasShadow.ShadowMapSize = new Vector2(hasShadow.ShadowMapWidth, hasShadow.ShadowMapHeight);
                    hasShadow.ShadowMatrix = Matrix4.Identity;
                }

                if (hasShadow.ShadowCamera == null)
                {

                    if (hasShadow is SpotLight) hasShadow.ShadowCamera = new PerspectiveCamera(renderer, hasShadow.ShadowCameraFov, hasShadow.ShadowCameraNear, hasShadow.ShadowCameraFar);
                    else if (hasShadow is DirectionalLight) hasShadow.ShadowCamera = new OrthographicCamera(hasShadow.ShadowCameraLeft, hasShadow.ShadowCameraRight, hasShadow.ShadowCameraTop, hasShadow.ShadowCameraBottom, hasShadow.ShadowCameraNear, hasShadow.ShadowCameraFar);
                    else throw new Exception("Unsupported light type for shadow");

                    scene.Add(hasShadow.ShadowCamera);
                    if (scene.AutoUpdate) scene.UpdateMatrixWorld();

                }

                if (hasShadow.ShadowCameraVisible /* && light.CameraHelper == null*/)
                {
                    throw new NotImplementedException();
                    //light.CameraHelper = new CameraHelper( hasShadow.ShadowCamera );
                    //hasShadow.ShadowCamera.Add( light.CameraHelper );
                }

                var virtualLight = light as VirtualLight;
                if (virtualLight != null && virtualLight.OriginalCamera == camera)
                {
                    UpdateShadowCamera(camera, light);
                }

                var shadowMap = hasShadow.shadowMap;
                var shadowMatrix = hasShadow.ShadowMatrix;
                var shadowCamera = hasShadow.ShadowCamera;

                shadowCamera.Position = Vector3.FromPosition(light.matrixWorld);
                matrixPosition = (light as HasTarget).Target;
                shadowCamera.LookAt(matrixPosition);
                shadowCamera.UpdateMatrixWorld();

                shadowCamera.matrixWorldInverse = Matrix4.GetInverse(shadowCamera.matrixWorld);

                //TODO : Creating helpers if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
                //if (hasShadow.ShadowCameraVisible) light.cameraHelper.update();

                // compute shadow matrix

                shadowMatrix = new Matrix4(0.5f, 0.0f, 0.0f, 0.5f,
                                            0.0f, 0.5f, 0.0f, 0.5f,
                                            0.0f, 0.0f, 0.5f, 0.5f,
                                            0.0f, 0.0f, 0.0f, 1.0f);

                shadowMatrix.Multiply(shadowCamera.projectionMatrix);
                shadowMatrix.Multiply(shadowCamera.matrixWorldInverse);

                // update camera matrices and frustum
                projectionScreenMatrix.MultiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
                frustum = Frustum.FromMatrix(projectionScreenMatrix);

                // render shadow map
                renderer.SetRenderTarget(shadowMap);
                renderer.Clear();

                // set object matrices & frustum culling

                renderList.Clear();
                ProjectObject(scene, scene, shadowCamera);

                // render regular objects
                foreach (var glObject in renderList)
                {
                    var o = glObject.Object;
                    var buffer = glObject.Buffer;

                    throw new NotImplementedException();
                }
            }

            // restore GL state
            var clearColor = renderer.ClearColor;
            GL.ClearColor(clearColor.R, clearColor.G, clearColor.B, 1);
            GL.Enable(EnableCap.Blend);

            if (renderer.shadowMapCullFace == CullFaceMode.Front) GL.CullFace(CullFaceMode.Back);

        }
예제 #6
0
        protected internal override void Render(Scene scene, Camera camera, int viewportWidth, int viewportHeight)
        {
            if (!(renderer.shadowMapEnabled && renderer.shadowMapAutoUpdate)) return;

            Update(scene, camera);
        }
예제 #7
0
        // Fit shadow camera's ortho frustum to camera frustum
        private void UpdateShadowCamera(Camera camera, VirtualLight light)
        {
            var min = Vector3.Infinity;
            var max = Vector3.NegativeInfinity;

            for (var i = 0; i < 8; i++)
            {

                var p = light.PointsFrustum[i];
                Projector.UnprojectVector(p, camera.projectionMatrix, camera.matrixWorld);

                p.Apply(light.ShadowCamera.matrixWorldInverse);

                min.Min(p);
                min.Max(p);
            }

            var ortho = light.ShadowCamera as OrthographicCamera;
            if (ortho != null)
            {
                ortho.left = min.x;
                ortho.right = max.x;
                ortho.top = max.y;
                ortho.bottom = min.y;
            }
            else
            {
                throw new NotImplementedException("Should this just ignore the perspective version?");
            }

            // can't really fit near/far
            //shadowCamera.near = _min.z;
            //shadowCamera.far = _max.z;
            light.ShadowCamera.UpdateProjectionMatrix();
        }
예제 #8
0
        private void ProjectObject(Scene scene, Object3D o, Camera shadowCamera)
        {
            if (o.IsVisible)
            {
                List<Scene.BufferInfo> glObjects;
                if (scene.glObjects.TryGetValue(o.Id, out glObjects))
                {
                    if (o.DoesCastShadow && (!o.frustumCulled || frustum.IntersectsObject(o)))
                    {
                        foreach(var glObject in glObjects)
                        { 
                            o.modelViewMatrix.MultiplyMatrices(shadowCamera.matrixWorldInverse, o.matrixWorld);
                            renderList.Add(glObject);
                        }
                    }

                    foreach (var c in o.Children) ProjectObject(scene, c, shadowCamera);
                }
            }
        }
예제 #9
0
 private void UpdateShadowCamera(Camera camera, Light light)
 {
     throw new NotImplementedException();
 }
예제 #10
0
 internal protected abstract void Render(Scene scene, Camera camera, int viewportWidth, int viewportHeight);
예제 #11
0
        private static void Init()
        {
            mediaPath = Path.GetFullPath("../../../../../js/r68/examples/");
            texturesPath = Path.Combine(mediaPath, "textures");
            renderer = new Renderer();

            scene = new Scene()
            {
                Fog = new FogLinear(Color.Black, 1500,2100)
            };

            camera = new PerspectiveCamera(renderer, 60, 1, 2100)
            {
                Position = new Vector3(0, 0, 1500)
            };


            cameraOrtho = new OrthographicCamera(renderer, 1, 10000)
        {
            Position = new Vector3(0, 0, 150)
        };
            sceneOrtho = new Scene();

            //var amount = 200;
            //var radius = 500;


            sceneOrtho.Add(new Mesh(new SphereGeometry(100, 50, 50), new MeshBasicMaterial(renderer) { Diffuse = Color.Red}));
            

            var group = new Object3D();

            var materialA = new SpriteMaterial(renderer)
            {
                DiffuseMap = new Texture(Path.Combine(texturesPath, "sprite0.png")),
                Diffuse = Color.White,
                UseFog = true,
            };

            spriteTL = new Sprite(renderer, materialA)
            {
                Scale = new Vector3(materialA.DiffuseMap.Resolution.Width,materialA.DiffuseMap.Resolution.Height,1),                
            };
            sceneOrtho.Add(spriteTL);

            spriteTR = new Sprite(renderer, materialA)
            {
                Scale = new Vector3(materialA.DiffuseMap.Resolution.Width, materialA.DiffuseMap.Resolution.Height, 1),
            };
            sceneOrtho.Add(spriteTR);

            spriteBL = new Sprite(renderer, materialA)
            {
                Scale = new Vector3(materialA.DiffuseMap.Resolution.Width, materialA.DiffuseMap.Resolution.Height, 1),
            };
            sceneOrtho.Add(spriteBL);

            spriteBR = new Sprite(renderer, materialA)
            {
                Scale = new Vector3(materialA.DiffuseMap.Resolution.Width, materialA.DiffuseMap.Resolution.Height, 1),
            };
            sceneOrtho.Add(spriteBR);

            spriteC = new Sprite(renderer, materialA)
            {
                Scale = new Vector3(materialA.DiffuseMap.Resolution.Width, materialA.DiffuseMap.Resolution.Height, 1),
            };
            sceneOrtho.Add(spriteC);

            UpdateHUDSprites();

            var materialB = new SpriteMaterial(renderer)
            {
                DiffuseMap = new Texture(Path.Combine(texturesPath, "sprite1.png")),
                Diffuse = Color.White,
                UseFog = true,
            };

            var materialC = new SpriteMaterial(renderer)
            {
                DiffuseMap = new Texture(Path.Combine(texturesPath, "sprite2.png")),
                Diffuse = Color.White,
                UseFog = true,
            };

            mediaPath = Path.Combine(mediaPath, "../../tests/");

        }
예제 #12
0
 protected internal override void Render(Scene scene, Camera camera, int viewportWidth, int viewportHeight)
 {
     if (!IsEnabled) return;
     Update(scene, camera);
 }
예제 #13
0
        protected internal override void Render(Scene scene, Camera camera, int viewportWidth, int viewportHeight)
        {
            sprites.Clear();

            scene.TraverseVisible(child =>
            {
                if (child is Sprite)
                {
                    sprites.Add(child as Sprite);
                }
            });

            if (sprites.Count == 0) return;

            // setup gl
            GL.UseProgram(program);

            GL.EnableVertexAttribArray(attributes["position"]);
            GL.EnableVertexAttribArray(attributes["uv"]);

            GL.Disable(EnableCap.CullFace);
            GL.Enable(EnableCap.Blend);

            GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
            GL.VertexAttribPointer(attributes["position"], 2, VertexAttribPointerType.Float, false, 2 * 8, 0);
            GL.VertexAttribPointer(attributes["uv"], 2, VertexAttribPointerType.Float, false, 2 * 8, 8);

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, elementBuffer);

            GL.UniformMatrix4(uniforms["projectionMatrix"], 1, false, camera.projectionMatrix.elements);

            GL.ActiveTexture(TextureUnit.Texture0);
            GL.Uniform1(uniforms["map"], 0);

            var oldFogType = 0;
            var sceneFogType = 0;
            var fog = scene.Fog;

            if (fog != null)
            {
                GL.Uniform3(uniforms["fogColor"], fog.Color.R, fog.Color.G, fog.Color.B);
                var linear = fog as FogLinear;

                if (linear != null)
                {
                    GL.Uniform1(uniforms["fogNear"], linear.Near);
                    GL.Uniform1(uniforms["fogFar"], linear.Far);

                    GL.Uniform1(uniforms["fogType"], 1);
                    oldFogType = 1;
                    sceneFogType = 1;
                }
                else
                {
                    var exponential = fog as FogExp2;
                    if (exponential != null)
                    {
                        GL.Uniform1(uniforms["fogDensity"], exponential.Density);
                        GL.Uniform1(uniforms["fogType"], 2);
                        oldFogType = 2;
                        sceneFogType = 2;
                    }
                    else
                    {
                        GL.Uniform1(uniforms["fogType"], 0);
                        oldFogType = 0;
                        sceneFogType = 0;
                    }
                }


                // update positions and sort
                foreach (var sprite in sprites)
                {
                    var material = sprite.Material;
                    sprite.modelViewMatrix.MultiplyMatrices(camera.matrixWorldInverse, sprite.matrixWorld);
                    sprite.Zdepth = -sprite.modelViewMatrix.elements[14];
                }
                sprites.Sort(painterSortStable);

                // render all sprites
                foreach (var sprite in sprites)
                {
                    var material = sprite.Material as SpriteMaterial;

                    GL.Uniform1(uniforms["alphaTest"], material.ShouldAlphaTest);
                    GL.UniformMatrix4(uniforms["modelViewMatrix"], 1, false, sprite.modelViewMatrix.elements);

                    var fogType = 0;

                    if (scene.Fog != null && material.UseFog)
                    {
                        fogType = sceneFogType;
                    }

                    if (oldFogType != fogType)
                    {
                        GL.Uniform1(uniforms["fogType"], fogType);
                        oldFogType = fogType;
                    }

                    if (material.DiffuseMap != null)
                    {
                        GL.Uniform2(uniforms["uvOffset"], material.DiffuseMap.Offset.x, material.DiffuseMap.Offset.y);
                        GL.Uniform2(uniforms["uvScale"], material.DiffuseMap.Repeat.x, material.DiffuseMap.Repeat.y);
                    }
                    else
                    {
                        GL.Uniform2(uniforms["uvOffset"], 0, 0);
                        GL.Uniform2(uniforms["uvScale"], 1, 1);
                    }

                    GL.Uniform1(uniforms["opacity"], material.Opacity);
                    GL.Uniform3(uniforms["color"], material.Diffuse.R, material.Diffuse.G, material.Diffuse.B);

                    GL.Uniform1(uniforms["rotation"], material.Rotation);
                    GL.Uniform2(uniforms["scale"], sprite.Scale.x, sprite.Scale.y);

                    renderer.SetBlending(material.Blending, material.BlendEquation, material.BlendSource, material.BlendDestination);
                    renderer.DepthTest = material.ShouldDepthTest;
                    renderer.DepthWrite = material.ShouldDepthWrite;

                    if (material.DiffuseMap != null && material.DiffuseMap.Resolution.Width > 0) renderer.SetTexture(material.DiffuseMap, 0);
                    else renderer.SetTexture(texture, 0);

                    GL.DrawElements(BeginMode.Triangles, 6, DrawElementsType.UnsignedShort, 0);

                }

                // restore gl
                GL.Enable(EnableCap.CullFace);
            }
        }
예제 #14
0
        private static void Init()
        {
            camera = new PerspectiveCamera(renderer, 30, 1, 10000 )
            {
                Position = new Vector3(0,0,100)
            };

				cameraRTT = new OrthographicCamera(renderer, -10000, 10000 )
                {
                    Position= new Vector3(0,0,100)
                };

            scene = new Scene();
            sceneRTT = new Scene();
		    sceneScreen = new Scene();

				var light = new DirectionalLight( Color.White )
                {
                    Position = Vector3.UnitZ.Normalized()
                };
            sceneRTT.Add( light );

				light = new DirectionalLight(new Color(0xffaaaa))
                {
                    Position = Vector3.UnitNegativeZ.Normalized(),
                    Intensity = 1.5f
                };
				sceneRTT.Add( light );

				rtTexture = new RenderTarget(renderer.Width, renderer.Height)
            {
                MinFilter = TextureMinFilter.Linear,
                MagFilter = TextureMagFilter.Nearest,
                Format = Three.Net.Renderers.PixelFormat.RGB
            };

            var vertexShaderSource = @"
varying vec2 vUv;
void main() 
{
	vUv = uv;
	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}";

            var fragment_shader_screenSource = @"
varying vec2 vUv;
uniform sampler2D tDiffuse;
void main() 
{
	gl_FragColor = texture2D( tDiffuse, vUv );
}";
            var fragment_shader_pass_1Source = @"
varying vec2 vUv;
uniform float time;
void main() 
{
	float r = vUv.x;
	if( vUv.y < 0.5 ) r = 0.0;
	float g = vUv.y;
	if( vUv.x < 0.5 ) g = 0.0;

	gl_FragColor = vec4( r, g, time, 1.0 );
}";
				material = new CustomShaderMaterial(renderer,vertexShaderSource,fragment_shader_pass_1Source, m => { });

				var materialScreen = new CustomShaderMaterial(renderer, vertexShaderSource, fragment_shader_screenSource, m => {})
                {
                    ShouldDepthWrite = false
                };

				var plane = new PlaneGeometry( renderer.Width, renderer.Height);
				var quad = new Mesh( plane, material )
                {
                    Position = new Vector3(0,0,-100)
                };
            sceneRTT.Add( quad );

				var geometry = new TorusGeometry( 100, 25, 15, 30 );

				var mat1 = new MeshPhongMaterial(renderer)
                {
                    Diffuse = new Color(0x555555),
                    Specular = new Color(0xffaa00),
                    Shininess = 5 
                };
				var mat2 = new MeshPhongMaterial(renderer)
                {
                    Diffuse = new Color(0x550000),
                    Specular = new Color(0xff2200),
                    Shininess = 5 
                };

				zmesh1 = new Mesh( geometry, mat1 )
                {
                    Position = new Vector3( 0, 0, 100 ),
                    Scale = new Vector3( 1.5f, 1.5f, 1.5f )
                };
				sceneRTT.Add( zmesh1 );

				zmesh2 = new Mesh( geometry, mat2 )
                {
                    Position = new Vector3( 0, 150, 100 ),
                    Scale = new Vector3( 0.75f, 0.75f, 0.75f)
                };
				sceneRTT.Add( zmesh2 );

				quad = new Mesh( plane, materialScreen ){
                    Position = new Vector3(0,0,-100)
                };
				sceneScreen.Add( quad );

				var n = 5;
            var sphereGeometry = new SphereGeometry( 10, 64, 32 );
            var material2 = new MeshBasicMaterial(renderer)
            {
                Diffuse = Color.White,
                DiffuseMap = rtTexture
            };

				for( var j = 0; j < n; j ++ ) {

					for( var i = 0; i < n; i ++ ) {

                        var mesh = new Mesh(sphereGeometry, material2)
                        {
                            Position = new Vector3(
                                ( i - ( n - 1 ) / 2 ) * 20, 
                                ( j - ( n - 1 ) / 2 ) * 20,
                                0),
                                Rotation = new Euler(0,-Mathf.Pi / 2, 0)
                        };
                        scene.Add( mesh );
					}
				}

                renderer.ShouldAutoClear = false;
        }
예제 #15
0
        public static CameraHelper Create(Renderer renderer, Camera camera)
        {
            var pointMap = new Dictionary<string, List<int>>();

            var geometry = new Geometry();
            var material = new LineBasicMaterial(renderer)
            {
                Diffuse = Color.White,
                VertexColors = VertexColorMode.Vertex
            };
            var cameraHelper = new CameraHelper(camera, geometry, material);

            //Colors
            var hexFrustum = new Color(0xffaa00);
            var hexCone = new Color(0xff0000);
            var hexUp = new Color(0x00aaff);
            var hexTarget = new Color(0xffffff);
            var hexCross = new Color(0x333333);

            // near
            cameraHelper.AddLine("n1", "n2", hexFrustum);
            cameraHelper.AddLine("n2", "n4", hexFrustum);
            cameraHelper.AddLine("n4", "n3", hexFrustum);
            cameraHelper.AddLine("n3", "n1", hexFrustum);
            
            // far
            cameraHelper.AddLine("f1", "f2", hexFrustum);
            cameraHelper.AddLine("f2", "f4", hexFrustum);
            cameraHelper.AddLine("f4", "f3", hexFrustum);
            cameraHelper.AddLine("f3", "f1", hexFrustum);
            
            // sides
            cameraHelper.AddLine("n1", "f1", hexFrustum);
            cameraHelper.AddLine("n2", "f2", hexFrustum);
            cameraHelper.AddLine("n3", "f3", hexFrustum);
            cameraHelper.AddLine("n4", "f4", hexFrustum);
            
            // cone
            cameraHelper.AddLine("p", "n1", hexCone);
            cameraHelper.AddLine("p", "n2", hexCone);
            cameraHelper.AddLine("p", "n3", hexCone);
            cameraHelper.AddLine("p", "n4", hexCone);
            
            // up
            cameraHelper.AddLine("u1", "u2", hexUp);
            cameraHelper.AddLine("u2", "u3", hexUp);
            cameraHelper.AddLine("u3", "u1", hexUp);
            
            // target
            cameraHelper.AddLine("c", "t", hexTarget);
            cameraHelper.AddLine("p", "c", hexCross);
            
            // cross
            cameraHelper.AddLine("cn1", "cn2", hexCross);
            cameraHelper.AddLine("cn3", "cn4", hexCross);
            cameraHelper.AddLine("cf1", "cf2", hexCross);
            cameraHelper.AddLine("cf3", "cf4", hexCross);

            cameraHelper.Update();
            return cameraHelper;
        }