using System; using System.Collections.Generic; using Oni.Collections; namespace Oni.Dae { internal class UnitConverter { private Scene scene; private float scale; private Set scaledValues; public static void Convert(Scene scene, float scale) { var converter = new UnitConverter { scene = scene, scale = scale, scaledValues = new Set() }; converter.Convert(); } private void Convert() { Convert(scene); } private void Convert(Node node) { foreach (var transform in node.Transforms) Convert(transform); foreach (var instance in node.Instances) Convert(instance); foreach (var child in node.Nodes) Convert(child); } private void Convert(Instance instance) { var geometryInstance = instance as GeometryInstance; if (geometryInstance != null) { Convert(geometryInstance.Target); return; } } private void Convert(Geometry geometry) { foreach (var primitives in geometry.Primitives) { // // TODO: this assumes that position sources are not reused. // foreach (var input in primitives.Inputs) { if (input.Semantic == Semantic.Position) Scale(input.Source.FloatData, input.Source.Stride); } } } private void Convert(Transform transform) { var translate = transform as TransformTranslate; if (translate != null) { Scale(translate.Values, 3); if (translate.HasAnimations) { for (int i = 0; i < translate.Animations.Length; i++) { Sampler s = translate.Animations[i]; translate.Animations[i] = s == null ? null : s.Scale(scale); } } return; } var matrix = transform as TransformMatrix; if (matrix != null) { matrix.Values[3] *= scale; matrix.Values[7] *= scale; matrix.Values[11] *= scale; return; } } private void Scale(float[] values, int stride) { if (!scaledValues.Add(values)) return; for (int i = 0; i + stride - 1 < values.Length; i += stride) { values[i + 0] *= scale; values[i + 1] *= scale; values[i + 2] *= scale; } } } }