public bool UpdateInstance(ulong instanceGUID, CGGameObject_C gameObject) { if (gameObject.DisplayInfo == null) { return(false); } var gameObjectDisplayInfo = gameObject.DisplayInfo; var positionMatrix = gameObject.PositionMatrix; var entry = gameObjectDisplayInfo.ID; if (_models.TryGetValue(entry, out WorldModel instance)) { return(instance.UpdateInstance(instanceGUID, ref positionMatrix)); } var modelSpawn = WorldModelCache.OpenInstance(_directory, Path.GetFileName(gameObjectDisplayInfo.Filename).Replace(".mdx", ".m2")); if (modelSpawn == null) { return(false); } var modelInstanceGUID = modelSpawn.UpdateInstance(instanceGUID, ref positionMatrix); // reference type, so it is irrelevant if we didn't manage to save it - a thread did before us! _models.TryAdd(gameObject.DisplayInfo.ID, modelSpawn); return(modelInstanceGUID); }
public void Render(int centerTileX, int centerTileY, int renderRange) { // todo implement global model if (!_isTiled) { return; } var wmoProgram = ShaderProgramCache.Instance.Get("wmo"); var view = Matrix4.Mult(Game.Camera.View, Game.Camera.Projection); var cameraDirection = Game.Camera.Forward; wmoProgram.Use(); wmoProgram.UniformMatrix("projection_view", false, ref view); wmoProgram.UniformVector("camera_direction", ref cameraDirection); wmoProgram.UniformVector("object_color", ref WMO_COLOR); foreach (var kv in _grids) { var xInRange = Math.Abs(kv.Value.X - centerTileX) <= renderRange; var yInRange = Math.Abs(kv.Value.Y - centerTileY) <= renderRange; if (!xInRange || !yInRange) { kv.Value.RemoveInstances(); } } for (var i = centerTileY - renderRange; i <= centerTileY + renderRange; ++i) { for (var j = centerTileX - renderRange; j <= centerTileX + renderRange; ++j) { if (!_grids.TryGetValue(PackTile(j, i), out var gridRenderer)) { LoadGrid(j, i); } else { gridRenderer.AddInstances(); } } } // Now that all instances are added, render everything in one single pass foreach (var kv in _grids.SelectMany(grid => grid.Value.Models).Distinct()) { var worldModel = WorldModelCache.OpenInstance(_directory, kv); if (worldModel == null) { continue; } worldModel.Render(); } }
public void LoadInstances(string directory, int mapID, int tileX, int tileY) { _directory = directory; X = tileX; Y = tileY; var filePath = Path.Combine(directory, "vmaps", $"{mapID:D3}_{tileX:D2}_{tileY:D2}.vmtile"); if (!File.Exists(filePath)) { return; } using (var reader = new BinaryReader(File.OpenRead(filePath))) { reader.BaseStream.Position += 8; // Skip magic var numModelBatches = reader.ReadInt32(); for (var i = 0; i < numModelBatches; ++i) { var modelSpawn = new ModelSpawn(directory, reader); reader.BaseStream.Position += 4; var modelName = modelSpawn.ModelName; var modelPosition = modelSpawn.PositionMatrix; var worldModel = WorldModelCache.OpenInstance(directory, modelName); if (!_instanceGUIDs.TryGetValue(modelName, out var storageDictionary)) { storageDictionary = _instanceGUIDs[modelName] = new Dictionary <ulong, Matrix4>(); } storageDictionary.Add(worldModel.AddInstance(ref modelPosition), modelPosition); } } _instancesRendered = true; }
public void RemoveInstances() { if (!_instancesRendered) { return; } _instancesRendered = false; foreach (var kv in _instanceGUIDs) { var worldModel = WorldModelCache.OpenInstance(_directory, kv.Key); if (worldModel == null) { continue; } foreach (var kv2 in kv.Value) { worldModel.RemoveInstance(kv2.Key); } } }
public void AddInstances() { if (_instancesRendered) { return; } _instancesRendered = true; foreach (var kv in _instanceGUIDs) { var worldModel = WorldModelCache.OpenInstance(_directory, kv.Key); if (worldModel == null) { continue; } foreach (var kv2 in kv.Value) { var instanceMatrix = kv2.Value; worldModel.AddInstance(ref instanceMatrix); } } }