public static bool Collision3D(BoundingSphere player, Object3D object1, Vector3 pos) { for (int i = 0; i < object1.Model.Meshes.Count; i++) { BoundingSphere bs1 = object1.Model.Meshes[i].BoundingSphere; bs1.Center += object1.Position; if (player.Intersects(bs1)) return true; } return false; }
public VertexStorageObject3D(VertexStorage vertexStorage) { this.vertexStorage = vertexStorage; this.Children.Modify(children => { int i = 0; foreach (var v in vertexStorage.Vertices()) { if (!v.IsMoveTo && !v.IsLineTo) { continue; } var localVertex = v; var localIndex = i++; var item = new Object3D() { Mesh = CreateCylinder(1, 1), Matrix = Matrix4X4.CreateTranslation(v.position.X, v.position.Y, 0), Color = Color.Green }; item.Invalidated += (s, e) => { System.Diagnostics.Debugger.Break(); //vertexStorage.modify_vertex(localIndex, item.Matrix.Position.X, localVertex.position.Y = item.Matrix.Position.Y); }; children.Add(item); } children.Add(generatedMesh = new Object3D() { Mesh = VertexSourceToMesh.Extrude(vertexStorage, 0.5), Color = new Color("#93CEFF99") }); }); this.Invalidated += (s, e) => { // Recompute path from content generatedMesh.Mesh = VertexSourceToMesh.Extrude(vertexStorage, 0.5); //VertexSourceToMesh.Revolve(vertexStorage)); }; }
public override void Apply(UndoBuffer undoBuffer) { // change this from a text object to a group var newContainer = new Object3D(); newContainer.CopyProperties(this, Object3DPropertyFlags.All); foreach (var child in this.Children) { newContainer.Children.Add(child.Clone()); } undoBuffer.AddAndDo(new ReplaceCommand(new List <IObject3D> { this }, new List <IObject3D> { newContainer })); }
public Task <IObject3D> CreateItem(ILibraryItem item, Action <double, string> reporter) { Mesh logomesh = null; using (var meshStream = AggContext.StaticData.OpenStream(Path.Combine("Stls", "openscad_logo.stl"))) { logomesh = Object3D.Load(meshStream, ".stl", CancellationToken.None).Mesh; } return(Task.FromResult <IObject3D>(new OpenScadObject3D() { Mesh = logomesh, // Set after load below ScriptPath = (item as ILibraryAssetStream)?.AssetPath })); }
private async void RunTest() { StaticData.RootPath = TestContext.CurrentContext.ResolveProjectPath(4, "StaticData"); MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); var root = new Object3D(); // now add a pinch var pinch1 = new PinchObject3D_3(); pinch1.Children.Add(new CubeObject3D()); await pinch1.Rebuild(); root.Children.Add(pinch1); Assert.AreEqual(3, root.Descendants().Count()); }
private void saveObjectConfig() { sceneSave.objectSaveList = new List <ObjectSave>(); for (int i = 0; i < scene.object3DList.Count; i++) { Object3D o = scene.object3DList[i]; ObjectSave objectSave = new ObjectSave(); objectSave.name = o.name; objectSave.type = o.type; objectSave.resourcePath = o.resourcePath; objectSave.rotate = o.object3D.transform.rotation.eulerAngles; objectSave.scale = o.object3D.transform.localScale; objectSave.translate = o.object3D.transform.position; sceneSave.objectSaveList.Add(objectSave); } }
private Color getNaturalColor(Object3D thing, Vector3 pos, Vector3 norm, Vector3 rd, Scene scene) { List <Color> colors = new List <Color>(); foreach (var light in scene.lights) { var ldis = light.pos - pos; var livec = Vector3.Normalize(ldis); var neatIsect = this.testRay(new Ray { Position = pos, Direction = livec }, scene); var isInShadow = (neatIsect == null) ? false : neatIsect.Value <= ldis.Length(); if (isInShadow) { colors.Add(Color.defaultColor); } else { var illum = Vector3.Dot(livec, norm); var lcolor = (illum > 0) ? Color.scale(illum, light.color) : Color.defaultColor; var specular = Vector3.Dot(livec, Vector3.Normalize(rd)); var scolor = (specular > 0) ? Color.scale((float)System.Math.Pow(specular, thing.surface.roughness), light.color) : Color.defaultColor; var outc = Color.plus(Color.defaultColor, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), Color.times(thing.surface.specular(pos), scolor))); colors.Add(outc); } } var cl = new Color(0, 0, 0); foreach (var c in colors) { cl.r += c.r; cl.g += c.g; cl.b += c.b; } return(cl); }
public Task <IObject3D> CreateItem(ILibraryItem item, Action <double, string> progressReporter) { return(Task.Run(async() => { IObject3D loadedItem = null; try { var streamInterface = item as ILibraryAssetStream; if (streamInterface != null) { using (var contentStream = await streamInterface.GetStream(progressReporter)) { if (contentStream != null) { // TODO: Wire up caching loadedItem = Object3D.Load(contentStream.Stream, Path.GetExtension(streamInterface.FileName), CancellationToken.None, null /*itemCache*/, progressReporter); // Set MeshPath for non-mcx content. Avoid on mcx to ensure serialization of children if (item is FileSystemFileItem fileItem && !string.Equals(Path.GetExtension(fileItem.FileName), ".mcx", StringComparison.OrdinalIgnoreCase)) { loadedItem.MeshPath = fileItem.Path; } } } } else { var contentInterface = item as ILibraryObject3D; loadedItem = await contentInterface?.GetObject3D(progressReporter); } } catch { } if (loadedItem != null) { // Push the original Library item name through to the IObject3D loadedItem.Name = item.Name; } // Notification should force invalidate and redraw progressReporter?.Invoke(1, ""); return loadedItem; })); }
public async Task LoadItemIntoScene(string itemPath, Vector2 bedCenter = new Vector2(), string itemName = null) { if (File.Exists(itemPath)) { BeginProgressReporting("Loading Mesh"); // TODO: How to we handle mesh load errors? How do we report success? IObject3D loadedItem = await Task.Run(() => Object3D.Load(itemPath, CancellationToken.None, progress: ReportProgress0to100)); if (loadedItem != null) { if (itemName != null) { loadedItem.Name = itemName; } // SetMeshAfterLoad Scene.Children.Modify(children => { if (loadedItem.Mesh != null) { // STLs currently load directly into the mesh rather than as a group like AMF children.Add(loadedItem); } else { children.AddRange(loadedItem.Children); } }); CreateGlDataObject(loadedItem); } else { partProcessingInfo.centeredInfoText.Text = string.Format("Sorry! No 3D view available\nfor this file."); } EndProgressReporting(); // Invoke LoadDone event LoadDone?.Invoke(this, null); } else { partProcessingInfo.centeredInfoText.Text = string.Format("{0}\n'{1}'", "File not found on disk.", Path.GetFileName(itemPath)); } }
// 初始化项目。 private void InitProject() { Miaokit.g_pIns.Load("data/upload/admin/project/20191018/5da9159b2005e.txt", delegate(byte[] aData) { if (null != aData) { Tile pTile = Miaokit.g_pIns.LoadTile(aData); int nIndex = 0; Debug.LogError("瓦片:" + pTile.handle + " " + pTile.sceneCount); foreach (Scene pScene in pTile.scenes) { if (2 != nIndex++) { continue; } Object3D pObject = pScene.object3D; float nHeight = 0.0f; Debug.LogError("场景:" + pScene.id + " " + pScene.layerCount); foreach (Layer pLayer in pScene.layers) { Object3D pLayerObj = pLayer.object3D; pLayerObj.transform.localPosition = new Vector3(0.0f, nHeight, 0.0f); nHeight += 9.0f; Debug.LogError("楼层:" + pLayer.id + " " + pLayer.siteCount); pLayer.Draw(); } } } }); PanoramaParam pParam = new PanoramaParam(); pParam.m_nLng = 0.0f; pParam.m_nLat = 0.0f; pParam.m_mTarget = Vector3.zero; pParam.m_nDistance = 128.0f; pParam.m_nPitch = 60.0f; pParam.m_nYaw = 0.0f; m_pCameraCtrl.Jump(CTRL_MODE.PANORAMA, pParam); }
public override void Flatten(UndoBuffer undoBuffer) { // we want to end up with just a group of all the visible mesh objects using (RebuildLock()) { var newChildren = new List <IObject3D>(); // push our matrix into a copy of our visible children foreach (var child in this.VisibleMeshes()) { var meshOnlyItem = new Object3D { Matrix = child.WorldMatrix(this), Color = child.WorldColor(this), MaterialIndex = child.WorldMaterialIndex(this), OutputType = child.WorldOutputType(this), Mesh = child.Mesh, Name = "Mesh".Localize() }; newChildren.Add(meshOnlyItem); } if (newChildren.Count > 1) { var group = new GroupObject3D { Name = this.Name }; group.Children.Modify(list => { list.AddRange(newChildren); }); newChildren.Clear(); newChildren.Add(group); } else if (newChildren.Count == 1) { newChildren[0].Name = this.Name; } // and replace us with the children undoBuffer.AddAndDo(new ReplaceCommand(new[] { this }, newChildren)); } Invalidate(InvalidateType.Children); }
public void LoadContent() { Model modeloSuelo = pM.Content.Load <Model>("fbx/suelo"); suelo = new Object3D("Suelo", new Vector3(0.0f, -1.2f, 0), modeloSuelo); suelo.setEscala(new Vector3(0.025f, 0.01f, 0.025f)); //Carga las 15 partes del cuerpo mySkeleton.init(); //Cargo las esferas para cada parte del cuerpo para el Avatar Model esfera = pM.Content.Load <Model>("fbx/esfera"); myAvatar.init(esfera); avanzarAnimacion(); }
internal static Object3D LoadAreaVisualMapAsObject3D(RomManager rommgr, LevelArea area) { var obj = new Object3D(); var dls = new List <DisplayList>(); foreach (Geopointer geop in area.AreaModel.Fast3DBuffer.DLPointers) { var dl = new DisplayList(); dl.FromStream(geop, rommgr, area.AreaID); dl.ToObject3D(obj, rommgr, area.AreaID); dls.Add(dl); } LoadedAreaVisualMapDisplayLists?.Invoke(dls.ToArray()); return(obj); }
public void SelectObject(Object3D ActiveObject3D) { if (ActiveObject3D != null) { SelectedObject = ActiveObject3D; SelectionType = SelectionTypes.Selected; MoveHelper.Position = ActiveObject3D.Position; RotationHelper.Position = ActiveObject3D.Position; } else { SelectedObject = null; SelectionType = SelectionTypes.None; MoveHelper.UnSelectArrow(); RotationHelper.UnSelectRing(); } }
/// <summary> /// Draws the GameObjects of the list /// </summary> /// <param name="gameTime">The object used for reacting to timechanges</param> /// <param name="spriteBatch">The SpriteBatch</param> public override void Draw(GameTime gameTime, SpriteBatch spriteBatch) { foreach (GameObject gameObject in gameObjects) { if (gameObject is Object3D) { Object3D gameObject3D = gameObject as Object3D; if (gameObject3D.Model != null) { gameObject3D.DrawCamera(player); gameObject3D.Draw(gameTime, spriteBatch); } } else if (gameObject is GameObjectGrid) { GameObjectGrid gameObjectGrid = gameObject as GameObjectGrid; foreach (GameObject obj in gameObjectGrid.Objects) { if (obj is Object3D) { Object3D gameObject3D = obj as Object3D; if (gameObject3D.Model != null) { gameObject3D.DrawCamera(player); gameObject3D.Draw(gameTime, spriteBatch); } } } } else { gameObject.Draw(gameTime, spriteBatch); } } if (isOnExit && !NoteInVicinity) { exitText.Draw(gameTime, spriteBatch); isOnExit = false; } else if (NoteInVicinity) { noteText.Draw(gameTime, spriteBatch); } }
public static void ExportModel(Object3D model, File3DLoaderModule modul) { var sfd = new SaveFileDialog(); string strFilter = General.GetExtensionFilter(modul); sfd.Filter = strFilter.Substring(strFilter.IndexOf("|", strFilter.IndexOf("|") + 1) + 1); // If modul <> LoaderModule.SimpleFileParser Then // MessageBoxEx.Show("Assimp and Aspose probably crashes at exporting.<br/>Please switch to SimpleFileParser in <b>Settings --> File Parser</b>.<br/>Assimp and Aspose will be working soon.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning) // End If if (sfd.ShowDialog() == DialogResult.OK) { // Await model.ToFileAsync(sfd.FileName, modul) modul.Invoke(model, sfd.FileName); } }
public void TestObject3D_CentreOfMass() { List <PointMass> massPoints = new List <PointMass>() { new PointMass(new Vector(-1, -1, 0), 1), new PointMass(new Vector(0, 0, 0), 1), new PointMass(new Vector(0, -1, 0), 1), new PointMass(new Vector(-1, 0, 0), 1), }; Object3D obj = new Object3D(massPoints); Vector result = obj.CentreOfGravity; Vector expected = new Vector(-0.5, -0.5, 0); Assert.AreEqual(result, expected); }
/** * Create an Android object and have it appear at the given location. * @param position The location where the Android should appear. */ private void CreateDroidAtPosition(Vector position) { // Create a droid on the surface var bot = GetBitmapFromAsset(this, "andy.png"); var object3D = new Object3D(); object3D.SetPosition(position); mScene.RootNode.AddChildNode(object3D); // Load the Android model asynchronously. object3D.LoadModel(mViroView.ViroContext, Android.Net.Uri.Parse("file:///android_asset/andy.obj"), Object3D.Type.Obj, new AsyncObjectListener(bot)); // Make the object draggable. object3D.Drag += (s, e) => { }; object3D.SetDragType(Node.DragType.FixedDistance); }
// Sample the world using Signed Distance Fields. public float QueryDatabase(Vector position, out Object3D hitObj) { hitObj = null; float distance = 1e9f; foreach (var obj in objects) { var dist = obj.GetDistance(position); if (distance > dist) { distance = dist; hitObj = obj; } } return(distance); }
public void OnObject3DLoaded(Object3D p0, Object3D.Type p1) { var objectTexture = new Texture(bot, Texture.Format.Rgba8, false, false); var material = new Material { DiffuseTexture = objectTexture, Roughness = 0.23f, Metalness = 0.7f }; // Give the material a more "metallic" appearance, so it reflects the environment map. // By setting its lighting model to PHYSICALLY_BASED, we enable PBR rendering on the // model. material.SetLightingModel(Material.LightingModel.PhysicallyBased); p0.Geometry.Materials = new List <Material>() { material }; }
void TimerTicked(object sender, EventArgs e) { angle += 2; for (int i = 0; i < 145; i++) { Object3D point = scene.Models[i] as Object3D; if (point is Sphere) { point.Rotation1 = Math3D.RotationZ(angle); } else { //point.Rotation1 = Math3D.RotationX(angle); } point.Rotation3 = Math3D.RotationZ(angle * 0.1); } }
public override Task Rebuild() { this.DebugDepth("Rebuild"); var rebuildLocks = this.RebuilLockAll(); var valuesChanged = false; return(TaskBuilder( "Reduce".Localize(), (reporter, cancellationToken) => { var newChildren = new List <Object3D>(); foreach (var sourceItem in SourceContainer.VisibleMeshes()) { var originalMesh = sourceItem.Mesh; var reducedMesh = Cut(originalMesh); var newMesh = new Object3D() { Mesh = reducedMesh, OwnerID = sourceItem.ID }; newMesh.CopyProperties(sourceItem, Object3DPropertyFlags.All); newChildren.Add(newMesh); } RemoveAllButSource(); SourceContainer.Visible = false; foreach (var child in newChildren) { this.Children.Add(child); } rebuildLocks.Dispose(); if (valuesChanged) { Invalidate(InvalidateType.DisplayValues); } Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children)); return Task.CompletedTask; })); }
public virtual void WrapItems(IEnumerable <IObject3D> items, UndoBuffer undoBuffer = null) { var parent = items.First().Parent; RebuildLocks parentLock = (parent == null) ? null : parent.RebuilLockAll(); var firstChild = new Object3D(); this.Children.Add(firstChild); // if the items we are replacing are already in a list if (parent != null) { if (undoBuffer != null) { foreach (var item in items) { firstChild.Children.Add(item.Clone()); } var replace = new ReplaceCommand(items, new[] { this }); undoBuffer.AddAndDo(replace); } else { parent.Children.Modify(list => { foreach (var item in items) { list.Remove(item); firstChild.Children.Add(item); } list.Add(this); }); } } else // just add them { firstChild.Children.Modify(list => { list.AddRange(items); }); } parentLock?.Dispose(); parent?.Invalidate(new InvalidateArgs(parent, InvalidateType.Children)); }
public void getLocatorPos(int[] result, int userId, bool worldRelative) { Object3D object3D = this.m_group.find(userId); if (object3D != null) { Node node = Node.m3g_cast(object3D); if (node != null) { this.getLocatorPos(result, node, worldRelative); return; } } result[0] = 0; result[1] = 0; result[2] = 0; }
/// <summary> /// Builds the model. /// </summary> /// <returns>The model.</returns> public Mesh3DGroup ToModel3D() { Mesh3DGroup modelGroup = new Mesh3DGroup(); int i = 0; foreach (var mesh in this.Meshes) { var gm = new Object3D { Geometry = mesh.ToMesh(), Material = this.Materials[i] }; modelGroup.Add(gm); i++; } return(modelGroup); }
private Color ComputeSpecular( Light l, V3 reflectedVec, V3 viewingVec, Object3D obj, V2 uv ) { Color specularIllu = new Color(0, 0, 0); if (reflectedVec * viewingVec > 0.0f) { specularIllu = l.Intensity * obj.Material.KSpecular * Mathf.Pow( reflectedVec * viewingVec, obj.Material.Shininess ); } return(specularIllu); }
public void Dispose() { _gameOverText.Dispose(); _gameOverText = null; _scoreText.Dispose(); _scoreText = null; _nameText.Dispose(); _nameText = null; _scoreboardText.Dispose(); _scoreboardText = null; _scoreboardNameText.Dispose(); _scoreboardNameText = null; _scoreboardScoreText.Dispose(); _scoreboardScoreText = null; _coinMesh.Dispose(); _coinMesh = null; }
public Position3D TryToFitObject(Object3D selectedObject) { double bestFittingQuality = Double.MaxValue; double localFittingQuality; Position2D positionToPlace = null; GuillotineCutContainer2D selectedContainer = GuillotineContainer; // No space in container - return from function if (selectedContainer.Subcontainers.Count == 0) { return(null); } GuillotineCutSubcontainer2D selectedSubcontainer = selectedContainer.Subcontainers.First() as GuillotineCutSubcontainer2D; // flattens object to 2D during single shelf placement Object2D selectedObject2D = new Object2D(selectedObject.Width, selectedObject.Height); foreach (GuillotineCutSubcontainer2D subcontainer in selectedContainer.Subcontainers) { if (ValidateObjectPlacement(selectedObject2D, subcontainer)) { localFittingQuality = CalculateFittingQuality(selectedObject2D, subcontainer); if (localFittingQuality < bestFittingQuality) { bestFittingQuality = localFittingQuality; selectedSubcontainer = subcontainer; positionToPlace = subcontainer.Position; } } } if (positionToPlace != null) { var newPlacedObject = selectedContainer.PlaceObject(selectedObject2D, positionToPlace) as PlacedObject2D; UpdateMaxDepth(selectedObject.Depth); selectedContainer.SplitSubcontainer(selectedSubcontainer, newPlacedObject); return(new Position3D(positionToPlace.X, positionToPlace.Y, this.Depth)); } else { return(null); } }
public Couleur specular(Object3D b, V3 v, Couleur color_surface) { V3 copy_v = new V3(v); copy_v.Normalize(); V3 copy_pos = new V3(this.direction); copy_pos.Normalize(); float sca = (copy_pos * copy_v); V3 v_curent_perfect = (copy_v * sca * 2.0f) - copy_pos; V3 v_current_oeil = -(v + b.getPosition()) + RenderSing.getCurrentRender().getEyesPosition(); float a = (float)Math.Pow((Math.Max((v_curent_perfect * v_current_oeil) / (v_curent_perfect.Norm() * v_current_oeil.Norm()), 0)), 25); return(this.couleur * a); }
public Viewer3D() : base("3D Viewer") { DisplayObject = new Object3D(); _oldCamera = Engine.Renderer.Camera; Engine.Renderer.Camera = new Camera3D(new Vector3(20, 50, 200)); Engine.Renderer.Camera.LookAt = Vector3.Normalize(Vector3.Zero - Engine.Renderer.Camera.Position); _skeletalShader ??= Engine.AssetLoader.Get <ShaderAsset>("Shaders/SkeletalAnim.xml"); if (_boneVerticesStream == null) { GLThread.ExecuteGLThreadAsync(() => { _boneVerticesStream = new RenderStreamBatch <VertexDataWithBones>(0, 1, false); }); } _terrain = new Terrain3D(32, 32, 16); _windowFlags |= ImGuiWindowFlags.MenuBar; }
/// Returns a shadow coefficient based on the list of lights visible /// from the currentPoint. protected float Occultation(Object3D currentObject, V3 currentPoint) { int lightsSize = Scene.Lights.Count; float shadowCoeff = 0.0f; foreach (Light l in Scene.Lights) { if (PointLightened(currentObject, currentPoint, l)) { shadowCoeff += 1.0f; } } shadowCoeff /= lightsSize; return(shadowCoeff); }
static void Main() { Console.WriteLine(FileUtils.GetFileExtension("example")); Console.WriteLine(FileUtils.GetFileExtension("example.pdf")); Console.WriteLine(FileUtils.GetFileExtension("example.new.pdf")); Console.WriteLine(FileUtils.GetFileNameWithoutExtension("example")); Console.WriteLine(FileUtils.GetFileNameWithoutExtension("example.pdf")); Console.WriteLine(FileUtils.GetFileNameWithoutExtension("example.new.pdf")); Object2D twoDimension = new Object2D(3, 4); Object3D threeDimension = new Object3D(5, 6, 7); Console.WriteLine("Distance in the 2D space = {0:f2}", twoDimension.CalcDistance2D(1, -2, 3, 4)); Console.WriteLine("Distance in the 3D space = {0:f2}", threeDimension.CalcDistance3D(5, 2, -1, 3, -6, 4)); Console.WriteLine("Volume = {0:f2}", threeDimension.CalcVolume()); Console.WriteLine("Diagonal XYZ = {0:f2}", threeDimension.CalcDiagonalXYZ()); Console.WriteLine("Diagonal XY = {0:f2}", threeDimension.CalcDiagonalXY()); Console.WriteLine("Diagonal XZ = {0:f2}", threeDimension.CalcDiagonalXZ()); Console.WriteLine("Diagonal YZ = {0:f2}", threeDimension.CalcDiagonalYZ()); }
byte[] byte_PlantGroup = new byte[Width * Height * 4]; //生長路面圖; #region 版本一 : 一口氣將所有典轉為世界座標 /* public void detect(Vector3D[,] RealWorldPoint, int Width, int Height, double rate) { Block_W = Width / PlantSize; //區塊切割寬數量 Block_H = Height / PlantSize; //區塊切割高數量 PlantRate = (int)(rate * (Block_H * Block_W)); PlantMask = new int[Block_H, Block_W]; //路面生長遮罩 PlantPoint = new Vector3D[Block_H, Block_W, 3]; PlantVector = new Vector3D[Block_H, Block_W]; #region 計算區塊的平面法向量 for (int y = 0; y < Block_H - 1; y++) { for (int x = 0; x < Block_W - 1; x++) { int PosIndex = y * Block_W + x; Point[] point = new Point[3]; Vector3D tempPoint = new Vector3D(); point[0].X = x * PlantSize; point[0].Y = y * PlantSize; point[1].X = (x + 1) * PlantSize; point[1].Y = y * PlantSize; point[2].X = x * PlantSize; point[2].Y = (y + 1) * PlantSize; //篩選平面區塊 for (int i = 0; i < 3; i++) { //取得世界空間座標 tempPoint = RealWorldPoint[point[i].X, point[i].Y]; if (tempPoint.Z < 0.8 || tempPoint.Z > 4) //取不到深度資訊時把遮罩設定為error { PlantMask[y, x] = ERROR_IDX; RecordPlantFlag = false; //取消紀錄PlantVector[] break; } else { RecordPlantFlag = true; PlantPoint[y, x, i] = tempPoint; } } //紀錄區塊平面法向量 if (RecordPlantFlag == true) { PlantVector[y, x] = CalculateMethod.PlaneVector(PlantPoint[y, x, 0], PlantPoint[y, x, 1], PlantPoint[y, x, 2]); if (PlantVector[y, x].Y > 0 && PlantVector[y, x].Z < 0) { PlantVector[y, x].Normalize(); } else { PlantMask[y, x] = ERROR_IDX; } } } } #endregion #region 計算路面方程式 Vector3D PlantNormal = new Vector3D(); Vector3D MinPoint = new Vector3D(); Vector3D[,] RecordPlant = new Vector3D[Block_H * Block_W, 2]; double minDistance = 0; for (int y = 0; y < Block_H; y++) for (int x = 0; x < Block_W; x++) { if (PlantMask[y, x] == DETECT_IDX) { GrowCount = 0; TempVector = PlantVector[y, x]; RefPoint = PlantPoint[y, x, 0]; GrowPlant(x, y); if (GrowCount >= PlantRate) { RefPoint = RefPoint / GrowCount; double distance = Math.Abs(Vector3D.DotProduct(TempVector, RefPoint) / Math.Pow((TempVector.X * TempVector.X + TempVector.Y * TempVector.Y + TempVector.Z * TempVector.Z), 0.5)); if (distance > minDistance) //找最低平面 { minDistance = distance; MinPoint = RefPoint; PlantNormal = TempVector; PlantNormal.Normalize(); //應該可以省略 } } else { PlantMask[y, x] = ERROR_IDX; } } } double plantParameter_a, plantParameter_b, plantParameter_c, plantParameter_d, plantParameter_ABC; //aX+bY+cZ = d plantParameter_a = PlantNormal.X; plantParameter_b = PlantNormal.Y; plantParameter_c = PlantNormal.Z; plantParameter_d = Vector3D.DotProduct(PlantNormal, MinPoint); plantParameter_ABC = Math.Pow(Math.Pow(PlantNormal.X, 2) + Math.Pow(PlantNormal.Y, 2) + Math.Pow(PlantNormal.Z, 2), 0.5); //到平面距離公式(分母) PlantNormal.Normalize(); plantParameter[0] = plantParameter_a; plantParameter[1] = plantParameter_b; plantParameter[2] = plantParameter_c; plantParameter[3] = plantParameter_d; plantParameter[4] = plantParameter_ABC; Console.WriteLine(plantParameter[0] + "," + plantParameter[1] + "," + plantParameter[2] + ". d = " + plantParameter[3]); #endregion } //畫地面 public void paint(Vector3D[,] RealWorldPoint, ColorImagePoint[] _mappedDepthLocations, ref byte[] draw_Floor) { int Width = Block_W * PlantSize; int Height = Block_H * PlantSize; for (int y = 0; y < 480; y++) for (int x = 0; x < 640; x++) { Vector3D RealPos = RealWorldPoint[x, y]; double d = (plantParameter[0] * RealPos.X + plantParameter[1] * RealPos.Y + plantParameter[2] * RealPos.Z - plantParameter[3]) / plantParameter[4]; if (d < 0) d = 0 - d; if (d < Distance && RealPos.Z > 0.8 && RealPos.Z < 4) { ColorImagePoint point = _mappedDepthLocations[y * 640 + x]; if ((point.X >= 0 && point.X < 640) && (point.Y >= 0 && point.Y < 480)) { draw_Floor[(point.Y * Width + point.X) * 4] = (byte)(0); draw_Floor[(point.Y * Width + point.X) * 4 + 1] = (byte)(255); draw_Floor[(point.Y * Width + point.X) * 4 + 2] = (byte)(255); } } } } */ #endregion #region 版本二 : 只轉需要用的點到世界座標 //全部偵測 public List<Object3D> Detect(double rate, SkeletonPoint[] skeleton, byte[] colorPixel) { Block_W = Width / PlantSize; //區塊切割寬數量 Block_H = Height / PlantSize; //區塊切割高數量 PlantRate = (int)(rate * (Block_H * Block_W)); PlantMask = new int[Block_H, Block_W]; //路面生長遮罩 PlantPoint = new Vector3D[Block_H, Block_W, 3]; PlantVector = new Vector3D[Block_H, Block_W]; List<Object3D> plants = new List<Object3D>(); #region 計算區塊的平面法向量 for (int y = 0; y < Block_H - 1; y++) { for (int x = 0; x < Block_W - 1; x++) { //int PosIndex = y * Block_W + x; Point[] point = new Point[3]; Vector3D tempPoint = new Vector3D(); point[0].X = x * PlantSize; point[0].Y = y * PlantSize; point[1].X = (x + 1) * PlantSize; point[1].Y = y * PlantSize; point[2].X = x * PlantSize; point[2].Y = (y + 1) * PlantSize; //篩選平面區塊 for (int i = 0; i < 3; i++) { //取得世界空間座標 tempPoint = CalculateMethod.TransPortVector(skeleton[point[i].X + point[i].Y * Width]); if (tempPoint.Y == Ythreshold) //Vector3D.Equals(tempPoint, new Vector3D(0, 0, 0)) || { PlantMask[y, x] = ERROR_IDX; RecordPlantFlag = false; //取消紀錄PlantVector[] ' byte_PlantGroup[4 * (x + y * Width) + 3] = (byte)0; for (int _i = 0; _i < PlantSize; _i++) for (int _j = 0; _j < PlantSize; _j++) { byte_PlantGroup[((point[i].Y + _i) * Width * 4) + (point[i].X + _j) * 4 + 3] = (byte)0; } break; } else { RecordPlantFlag = true; PlantPoint[y, x, i] = tempPoint; } } //紀錄區塊平面法向量 if (RecordPlantFlag == true) { tempPoint = CalculateMethod.TransPortVector(skeleton[((x + 1) * PlantSize) + ((y + 1) * PlantSize) * Width]); Vector3D tempVector = CalculateMethod.PlaneVector(tempPoint, PlantPoint[y, x, 1], PlantPoint[y, x, 2]); PlantVector[y, x] = CalculateMethod.PlaneVector(PlantPoint[y, x, 0], PlantPoint[y, x, 1], PlantPoint[y, x, 2]); //統一方向 if (PlantVector[y, x].Y < 0) PlantVector[y, x] = PlantVector[y, x] * -1; if (tempVector.Y < 0) tempVector = tempPoint * -1; //PlantVector[y, x] += tempVector; PlantVector[y, x].Normalize(); } } } #endregion #region 計算路面方程式 Vector3D PlantNormal = new Vector3D(); Vector3D MinPoint = new Vector3D(); Vector3D[,] RecordPlant = new Vector3D[Block_H * Block_W, 2]; Object3D obj = new Object3D(); double minDistance = 5; int id = 0; for (int y = 0; y < Block_H; y++) for (int x = 0; x < Block_W; x++) { if (PlantMask[y, x] == DETECT_IDX) { Group_R = (byte)random.Next(100, 255); Group_G = (byte)random.Next(100, 255); Group_B = (byte)random.Next(100, 255); obj = new Object3D(); maxDis = Double.MinValue; GrowCount = 0; TempVector = PlantVector[y, x]; RefPoint = PlantPoint[y, x, 0]; PrePoint = PlantPoint[y, x, 0]; GrowPlant(x, y, ref obj, skeleton, colorPixel); if (GrowCount >= PlantRate) { Console.WriteLine("plant id " + id + "," + maxDis); RefPoint = RefPoint / GrowCount; //因為皆為平面,故法向量相差不大,直接取其平均點的Y值作為高度判斷,取最低點 double distance = RefPoint.Y; if (distance < minDistance) //找最低平面 { minDistance = distance; MinPoint = RefPoint; //嚴格講起來是取平均點 PlantNormal = TempVector; PlantNormal.Normalize(); //應該可以省略 } if (obj.points.Count != 0) { obj.max_plant.normal_vector = TempVector; obj.max_plant.normal_vector.Normalize(); obj.max_plant.d = Vector3D.DotProduct(obj.max_plant.normal_vector, RefPoint); obj.max_plant.height = Math.Abs(RefPoint.Y); obj.max_plant.draw_range[0] = new System.Windows.Point(obj.points.Min(p => p.X), obj.points.Min(p => p.Y)); obj.max_plant.draw_range[1] = new System.Windows.Point(obj.points.Max(p => p.X), obj.points.Max(p => p.Y)); //取得平面的範圍 obj.GetRange(Ythreshold, true); obj.max_plant.plant_range[0] = new Point3D(obj.cube_range[0].X, RefPoint.Y, obj.cube_range[0].Z); obj.max_plant.plant_range[1] = new Point3D(obj.cube_range[1].X, RefPoint.Y, obj.cube_range[1].Z); obj.cube_prange[0] = obj.max_plant.draw_range[0]; obj.cube_prange[1] = obj.max_plant.draw_range[1]; obj.ID = id; for (int i = 0; i < 256; i++) { obj.xhistrogram[i] /= obj.points.Count; } plants.Add(obj); id++; } } else { PlantMask[y, x] = ERROR_IDX; byte_PlantGroup[4 * (x + y * Width) + 3] = (byte)0; for (int i = 0; i < PlantSize; i++) for (int j = 0; j < PlantSize; j++) { byte_PlantGroup[((y * PlantSize + i) * Width * 4) + (x * PlantSize + j) * 4 + 3] = (byte)255; } } } } double plantParameter_a, plantParameter_b, plantParameter_c, plantParameter_d, plantParameter_ABC; //aX+bY+cZ = d plantParameter_a = PlantNormal.X; plantParameter_b = PlantNormal.Y; plantParameter_c = PlantNormal.Z; plantParameter_d = Vector3D.DotProduct(PlantNormal, MinPoint); plantParameter_ABC = Math.Pow(Math.Pow(PlantNormal.X, 2) + Math.Pow(PlantNormal.Y, 2) + Math.Pow(PlantNormal.Z, 2), 0.5); //到平面距離公式(分母) //PlantNormal.Normalize(); plantParameter[0] = plantParameter_a; plantParameter[1] = plantParameter_b; plantParameter[2] = plantParameter_c; plantParameter[3] = plantParameter_d; plantParameter[4] = plantParameter_ABC; Floor.roadFunction = new Vector3D(plantParameter_a, plantParameter_b, plantParameter_c); Floor.d = plantParameter_d; return plants; #endregion }
public List<Vector3D> Detect(Object3D obj, List<Object3D> objects) { for (int o = 0; o < objects.Count; o++) { if (objects[o].ID != obj.ID) { for (int i = 0; i < objects[o].points.Count; i++) { double x = objects[o].points[i].X; double y = objects[o].points[i].Y; detectmarker[(int)(x + y * W)] = ERROR; } } } avgDis = 0; maxDis = 0; cdis = 0; ctotal = 0; bigavgDis = 0; maxdisPoint = new Vector3D(); int SX = (int)(obj.max_plant.draw_range[0].X + obj.max_plant.draw_range[1].X) / 2; int SY = (int)(obj.max_plant.draw_range[0].Y + obj.max_plant.draw_range[1].Y) / 2; pB = colorPixels[4 * (int)(SX + SY * W) + 0]; pG = colorPixels[4 * (int)(SX + SY * W) + 1]; pR = colorPixels[4 * (int)(SX + SY * W) + 2]; pdepth = depth[SX, SY]; p3dpoint = CalculateMethod.TransPortVector(skeleton[(int)(SX + SY * W)]); cSY = 0.299 * pR + 0.587 * pG + 0.114 * pB; double dx = obj.max_plant.draw_range[1].X - obj.max_plant.draw_range[0].X; double dy = obj.max_plant.draw_range[1].Y - obj.max_plant.draw_range[0].Y; try { if (pdepth != Ythreshold) GrowColor(SX, SY); else Console.WriteLine("start error"); Console.WriteLine("avgDis = " + (double)avgDis / cdis + ", maxdis " + maxDis + " count " + cdis + " ctotal " + ctotal + ", bigavg " + (double)bigavgDis / (ctotal - cdis)); //Console.WriteLine("max point " + maxdisPoint); avgDis = 0; maxDis = 0; cdis = 0; ctotal = 0; bigavgDis = 0; maxdisPoint = new Vector3D(); } catch (StackOverflowException error) { Console.WriteLine(error); } return newpoints; }
public ExitTile(string pathID) : base(pathID, "ExitTile") { exitObject = new Object3D("Misc Level Objects\\Trapdoor\\Trapdoor Model", "Trapdoor"); }
internal void add(Object3D poptart) { throw new NotImplementedException(); }
private Color getNaturalColor(Object3D thing, Vector3 pos, Vector3 norm, Vector3 rd, Scene scene) { List<Color> colors = new List<Color>(); foreach (var light in scene.lights) { var ldis = light.pos - pos; var livec = Vector3.Normalize(ldis); var neatIsect = this.testRay(new Ray { Position = pos, Direction = livec }, scene); var isInShadow = (neatIsect == null) ? false : neatIsect.Value <= ldis.Length(); if (isInShadow) { colors.Add(Color.defaultColor); } else { var illum = Vector3.Dot(livec, norm); var lcolor = (illum > 0) ? Color.scale(illum, light.color) : Color.defaultColor; var specular = Vector3.Dot(livec, Vector3.Normalize(rd)); var scolor = (specular > 0) ? Color.scale((float)System.Math.Pow(specular, thing.surface.roughness), light.color) : Color.defaultColor; var outc = Color.plus(Color.defaultColor, Color.plus(Color.times(thing.surface.diffuse(pos), lcolor), Color.times(thing.surface.specular(pos), scolor))); colors.Add(outc); } } var cl = new Color(0, 0, 0); foreach (var c in colors) { cl.r += c.r; cl.g += c.g; cl.b += c.b; } return cl; }
public EntryTile(string pathID) : base(pathID, "EntryTile") { trapdoor = new Object3D("Misc Level Objects\\Trapdoor\\Trapdoor Model", "Trapdoor"); }
public Object3D Detect(int SX, int SY, int EX, int EY, double rate, Vector3D[] realpoints, double goal_height) { Block_W = (EX - SX) / PlantSize; //區塊切割寬數量 Block_H = (EY - SY) / PlantSize; //區塊切割高數量 PlantRate = (int)(rate * (Block_H * Block_W)); PlantMask = new int[Block_H, Block_W]; //路面生長遮罩 PlantPoint = new Vector3D[Block_H, Block_W, 3]; PlantVector = new Vector3D[Block_H, Block_W]; List<Object3D> objects = new List<Object3D>(); #region 計算區塊的平面法向量 for (int y = 0; y < Block_H - 1; y++) { for (int x = 0; x < Block_W - 1; x++) { //int PosIndex = y * Block_W + (x + SX); Point[] point = new Point[3]; Vector3D tempPoint = new Vector3D(); point[0].X = x * PlantSize + SX; point[0].Y = y * PlantSize + SY; point[1].X = (x + 1) * PlantSize + SX; point[1].Y = y * PlantSize + SY; point[2].X = x * PlantSize + SX; point[2].Y = (y + 1) * PlantSize + SY; //篩選平面區塊 for (int i = 0; i < 3; i++) { //取得世界空間座標 tempPoint = realpoints[point[i].X + point[i].Y * Width]; if (Vector3D.Equals(tempPoint, new Vector3D(0, 0, 0)) || tempPoint.Y == Ythreshold) { PlantMask[y, x] = ERROR_IDX; RecordPlantFlag = false; //取消紀錄PlantVector[] break; } else { RecordPlantFlag = true; PlantPoint[y, x, i] = tempPoint; } } //紀錄區塊平面法向量 if (RecordPlantFlag == true) { PlantVector[y, x] = CalculateMethod.PlaneVector(PlantPoint[y, x, 0], PlantPoint[y, x, 1], PlantPoint[y, x, 2]); //統一方向 if (PlantVector[y, x].Y < 0) PlantVector[y, x] = PlantVector[y, x] * -1; PlantVector[y, x].Normalize(); } } } #endregion #region 求出區域最大平面 Vector3D[,] RecordPlant = new Vector3D[Block_H * Block_W, 2]; List<Point> plan_points = new List<Point>(); List<Point> relation = new List<Point>(); double maxGrowCount = 0; int id = 0; int newid = 0; for (int y = 0; y < Block_H; y++) for (int x = 0; x < Block_W; x++) { if (PlantMask[y, x] == DETECT_IDX) { Group_R = (byte)random.Next(0, 255); Group_G = (byte)random.Next(0, 255); Group_B = (byte)random.Next(0, 255); plan_points.Clear(); GrowCount = 0; TempVector = PlantVector[y, x]; RefPoint = PlantPoint[y, x, 0]; GrowPlant(x, y, ref plan_points, SX, SY); if (GrowCount >= PlantRate) { RefPoint = RefPoint / GrowCount; Vector3D test = TempVector; test.Normalize(); if (plan_points.Count != 0) { //找最大平面 // 找高度最接近的平面 //if (goal_height != -1) //{ // //if (GrowCount > maxGrowCount) // if (Math.Abs(Math.Abs(RefPoint.Y) - goal_height) < maxGrowCount) // { // //maxGrowCount = GrowCount; // maxGrowCount = Math.Abs(Math.Abs(RefPoint.Y) - goal_height); // newid = id; // } //} //else double AngleIJ = Vector3D.AngleBetween(test, Floor.roadFunction); { if (GrowCount > maxGrowCount && Math.Abs(RefPoint.Y) > 0.1 && AngleIJ < 10) // { maxGrowCount = GrowCount; newid = id; } } relation.Add(new Point(GrowCount, id)); //求出範圍 double minx = Double.MaxValue, maxx = Double.MinValue, minz = Double.MaxValue, maxz = Double.MinValue; foreach (Point p in plan_points) { Vector3D tmp = realpoints[p.X + p.Y * Width]; if (tmp.Y != Ythreshold) { if (tmp.X < minx) minx = tmp.X; if (tmp.X > maxx) maxx = tmp.X; if (tmp.Z < minz) minz = tmp.Z; if (tmp.Z > maxz) maxz = tmp.Z; } } //求出物體資訊 Object3D object3d = new Object3D(); object3d.max_plant.normal_vector = TempVector; object3d.max_plant.normal_vector.Normalize(); object3d.max_plant.d = Vector3D.DotProduct(object3d.max_plant.normal_vector, RefPoint); object3d.max_plant.draw_range[0] = new System.Windows.Point(plan_points.Min(p => p.X), plan_points.Min(p => p.Y)); object3d.max_plant.draw_range[1] = new System.Windows.Point(plan_points.Max(p => p.X), plan_points.Max(p => p.Y)); object3d.max_plant.center = new Vector3D((object3d.cube_range[0].X + object3d.cube_range[1].X) / 2, RefPoint.Y, (object3d.cube_range[1].Z + object3d.cube_range[0].Z) / 2); object3d.max_plant.height = Math.Abs(RefPoint.Y); object3d.cube_range[0] = object3d.max_plant.plant_range[0] = new Point3D(minx, RefPoint.Y, minz); object3d.cube_range[1] = object3d.max_plant.plant_range[1] = new Point3D(maxx, RefPoint.Y, maxz); object3d.ID = id; objects.Add(object3d); id++; } } else { PlantMask[y, x] = ERROR_IDX; } } } #endregion //relation.Sort(Tools.ComparePointX); //relation.ToArray(); //if (goal_height != -1) //{ // for (int i = 0; i < relation.Count; i++) // { // Object3D tmp = objects.Find(p => p.ID == relation[i].Y); // if (Math.Abs(tmp.max_plant.height - goal_height) < 0.1) // { // newid = relation[i].Y; // break; // } // } //} //else //{ // for (int i = 0; i < relation.Count; i++) // { // Object3D tmp = objects.Find(p => p.ID == relation[i].Y); // if (Math.Abs(tmp.max_plant.height - 0.1) >= 0.1) // { // newid = relation[i].Y; // break; // } // } //} Object3D newobject = objects.Find(p => p.ID == newid); if(newobject != null) Console.WriteLine("max grow count " + maxGrowCount + ", " + Vector3D.AngleBetween(newobject.max_plant.normal_vector, Floor.roadFunction)); return newobject; }
private Color getReflectionColor(Object3D thing, Vector3 pos, Vector3 normal, Vector3 rd, Scene scene, int depth) { var n = thing.surface.reflect(pos); var c = this.traceRay(new Ray { Position = pos, Direction = rd }, scene, depth + 1); return Color.scale(thing.surface.reflect(pos), c); }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // call LoadContent on all used components that implement it. testRasterizer.loadContent(GraphicsDevice, Content); // Load a triangle mesh. testMesh = new TriangleMesh("imrod_walk_high", Content); // Create a BFSOctree out of that mesh. testObj = new Object3D(testMesh.toBFSOctree(7), false); // Store the octree into a binary file. //testObj.getData().export("imrod.asvo"); testObj.rotate(Vector3.UnitX, MathHelper.PiOver2); System.GC.Collect(); ks = Keyboard.GetState(); }
/// <summary> /// Creates a render object job. When executed it will render <paramref name="object3D"/> from /// <paramref name="cam"/>'s point of view with <paramref name="rasterizer"/>. /// </summary> /// <param name="object3D">The 3d object to be rendered.</param> /// <param name="camera">The camera from which object3d shall be rendered.</param> /// <param name="rasterizer">The rasterizer to use for the /// rendering process.</param> public RenderObjectJob(Object3D object3D, Camera camera, Rasterizer rasterizer) { _object3D = object3D; _camera = camera; _rasterizer = rasterizer; }
private void GrowPlant(int x, int y, ref Object3D obj, SkeletonPoint[] skeleton, byte[] colorPixel) { Vector3D temp = TempVector; temp.Normalize(); double DP = Vector3D.DotProduct(temp, PlantVector[y, x]); //內積 限制角度範圍 30度0.86 45度 0.7 double Dis = Tools.Distance(PrePoint, PlantPoint[y, x, 0]); if ((x > 0 && x < Block_W - 1) && (y > 0 && y < Block_H - 1) && (DP > 0.86) && Dis <= 0.3)// { obj.points.Add(new System.Windows.Point(x * PlantSize, y * PlantSize)); obj.points3d.Add(PlantPoint[y, x, 0]); PlantMask[y, x] = TAKE_IDX; RefPoint = RefPoint + PlantPoint[y, x, 0]; TempVector = TempVector + PlantVector[y, x]; PrePoint = PlantPoint[y, x, 0]; GrowCount++; //計算平面數量 if (Dis > maxDis) maxDis = Dis; //測試 for (int i = 0; i < PlantSize; i++) for (int j = 0; j < PlantSize; j++) { byte_PlantGroup[((y * PlantSize + i) * Width * 4) + (x * PlantSize + j) * 4 + 2] = (byte)Group_R; byte_PlantGroup[((y * PlantSize + i) * Width * 4) + (x * PlantSize + j) * 4 + 1] = (byte)Group_G; byte_PlantGroup[((y * PlantSize + i) * Width * 4) + (x * PlantSize + j) * 4 + 0] = (byte)Group_B; //加上高度值踢掉物體部分 , 避免抓到物體高度 Vector3D tmp = CalculateMethod.TransPortVector(skeleton[(int)(x * PlantSize + j) + (int)(y * PlantSize + i) * Width]); double _Dis = Tools.Distance(PrePoint, tmp); if (tmp.Y != Ythreshold && tmp.Y >= 0.08 && _Dis <= 0.3) { obj.points.Add(new System.Windows.Point(x * PlantSize + j, y * PlantSize + i)); obj.points3d.Add(tmp); } int B = colorPixel[(int)((y * PlantSize + i) * Width + x * PlantSize + j) * 4 + 0]; int G = colorPixel[(int)((y * PlantSize + i) * Width + x * PlantSize + j) * 4 + 1]; int R = colorPixel[(int)((y * PlantSize + i) * Width + x * PlantSize + j) * 4 + 2]; double U = (-0.169 * R - 0.331 * G + 0.500 * B + 128); //量化 double Y = 0.299 * R + 0.587 * G + 0.114 * B; obj.xhistrogram[(int)U]++; } if (PlantMask[y, (x - 1)] == DETECT_IDX) //left { GrowPlant(x - 1, y, ref obj, skeleton, colorPixel); } if (PlantMask[(y - 1), x] == DETECT_IDX) //up { GrowPlant(x, y - 1, ref obj, skeleton, colorPixel); } if (PlantMask[(y + 1), x] == DETECT_IDX) //down { GrowPlant(x, y + 1, ref obj, skeleton, colorPixel); } if (PlantMask[y, (x + 1)] == DETECT_IDX) //right { GrowPlant(x + 1, y, ref obj, skeleton, colorPixel); } //if (PlantMask[(y - 1), (x - 1)] == DETECT_IDX) //left //{ // GrowPlant(x - 1, y - 1, ref obj, skeleton, colorPixel); //} //if (PlantMask[(y - 1), (x + 1)] == DETECT_IDX) //up //{ // GrowPlant((x + 1), y - 1, ref obj, skeleton, colorPixel); //} //if (PlantMask[(y + 1), (x - 1)] == DETECT_IDX) //down //{ // GrowPlant(x - 1, y + 1, ref obj, skeleton, colorPixel); //} //if (PlantMask[(y + 1), (x + 1)] == DETECT_IDX) //right //{ // GrowPlant(x + 1, y + 1, ref obj, skeleton, colorPixel); //} } }
/// <summary> /// Renders the sparse voxel octree stored in <paramref name="obj"/>. /// /// - Viewing frustum culling /// - Level of detail /// </summary> /// <param name="object3D">The object to be rendered.</param> /// <param name="fromPerspective">The camera this model shall be rendered from.</param> /// <param name="threadIndex">The index of the calling thread, starting by 0.</param> public void render(Object3D object3D, Camera fromPerspective, int threadIndex) { _depthBuffer.zeroOut(threadIndex); float dimension = -0.5f * object3D.getData().dimension; Vector3 octreeMin = new Vector3(dimension, dimension, dimension); traverse(object3D, 0, 0, 0, 0, fromPerspective.getProjectionMatrix(), object3D.getTransformation() * fromPerspective.getViewMatrix(), object3D.getTransformation() * fromPerspective.getViewProjectionMatrix(), 0, 0.0f, threadIndex, octreeMin); }
/// <summary> /// Traverses all octree nodes and draws them. Used by <see cref="Rasterizer.render"/>. /// </summary> private void traverse(Object3D obj, uint offset, int x, int y, int z, Matrix projection, Matrix worldView, Matrix worldViewProjection, byte level, float halfDim, int threadIndex, Vector3 octreeMin) { if (level == 2 && offset % JobCenter.getWorkerCount() != threadIndex) return; int gridResolution = 1 << level; float gridDimension = obj.getData().dimension; Vector3 xyzTimesGridDim = new Vector3(x, y, z) * gridDimension; float gridResolutionMul = 1.0f / gridResolution; Vector3 min = octreeMin + xyzTimesGridDim * gridResolutionMul; xyzTimesGridDim += new Vector3(gridDimension); Vector3 max = octreeMin + xyzTimesGridDim * gridResolutionMul; float dimension = max.X - min.X; bool subDivide = false; Vector3 center = Vector3.Lerp(min, max, 0.5f); Vector3 center2 = center + new Vector3(0, 0, dimension); VisualData vd = offset >= obj.getData()._innerNodes.Length ? obj.getData()._leaves[offset - obj.getData()._innerNodes.Length].visualData : obj.getData()._innerNodes[offset].visualData; Vector3 posIn, posOut; posOut = Vector3.Zero; if (vd.boneWeights.X > 0.0f) { posIn = center; Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex0]); posOut += vd.boneWeights.X * posIn; } if (vd.boneWeights.Y > 0.0f) { posIn = center; Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex1]); posOut += vd.boneWeights.Y * posIn; } if (vd.boneWeights.Z > 0.0f) { posIn = center; Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex2]); posOut += vd.boneWeights.Z * posIn; } if (vd.boneWeights.W > 0.0f) { posIn = center; Math3DHelper.mul(ref posIn, ref obj.getData()._animation[obj.frame, vd.boneIndex3]); posOut += vd.boneWeights.W * posIn; } center = posOut; if (offset >= obj.getData()._innerNodes.Length) { Math3DHelper.mul(ref center, ref worldViewProjection); halfDim *= 0.5f * dimension; } else { Math3DHelper.mul(ref center, ref worldView); Vector3 dimVec = new Vector3(0.5f * dimension, 0, center.Z); Math3DHelper.mul(ref center, ref projection); Math3DHelper.mul(ref dimVec, ref projection); halfDim = dimVec.X; subDivide = halfDim > pixelWidth; } if (subDivide) { float minusOneminusHalfDim = -1.0f - halfDim; float onePlusHalfDim = 1.0f + halfDim; if (center.X < minusOneminusHalfDim || center.X > onePlusHalfDim || center.Y < minusOneminusHalfDim || center.Y > onePlusHalfDim || center.Z < minusOneminusHalfDim + 1.0f || center.Z > onePlusHalfDim) return; Vector3 halfVec = 0.5f * (max - min); byte childIndex = 0; uint mask, index = 0; mask = obj.getData()._innerNodes[offset].childMask; index = obj.getData()._innerNodes[offset].childIndex; for (int i = 0; i < 8; ++i) { if ((mask & (byte)(1u << i)) != 0) { traverse(obj, index + childIndex, x * 2 + (i & 1), y * 2 + ((i & 2) >> 1), z * 2 + ((i & 4) >> 2), projection, worldView, worldViewProjection, (byte)(level + 1), halfDim, threadIndex, octreeMin); ++childIndex; } } } else { center.X = center.X * 0.5f + 0.5f; center.Y = 1.0f - (center.Y * 0.5f + 0.5f); int centerX, centerY; centerX = (int)Math3DHelper.round(center.X * horRes); centerY = (int)Math3DHelper.round(center.Y * vertRes); if (centerX < 0 || centerX >= horRes || centerY < 0 || centerY >= vertRes) return; int index = centerY * horRes + centerX; Vector3 normal; if (offset < obj.getData()._innerNodes.Length) normal = obj.getData()._innerNodes[offset].visualData.normal; else normal = obj.getData()._leaves[offset - obj.getData()._innerNodes.Length].visualData.normal; Matrix rotMatrix = obj.getRotation(); Math3DHelper.mul(ref normal, ref rotMatrix); byte color = (byte) MathHelper.Max(0, Vector3.Dot(normal, Vector3.UnitY) * 255); if (center.Z < _depthBuffer._elements[threadIndex][index]) { if (halfDim > _depthBuffer._maxDims[threadIndex]) _depthBuffer._maxDims[threadIndex] = halfDim; _colorBuffer[threadIndex][index].R = color; _colorBuffer[threadIndex][index].G = color; _colorBuffer[threadIndex][index].B = color; _depthBuffer._elements[threadIndex][index] = center.Z; } } }