internal void ValidateJoints(Validation.ValidationContext result, int jwset, int jointsCount) { var jj = this.AsVector4Array(); void _CheckJoint(Validation.ValidationContext r, float v, int idx, string n) { if (!v._IsReal()) { result.AddError(this, $"JOINTS_{jwset}[{idx}].{n} value {v} is not finite"); } if ((v % 1) != 0) { result.AddError(this, $"JOINTS_{jwset}[{idx}].{n} value {v} should be a round value"); } if (v < 0 || v >= jointsCount) { result.AddError(this, $"JOINTS_{jwset}[{idx}].{n} value {v} is out of range 0-{jointsCount}"); } } for (int i = 0; i < jj.Count; ++i) { var jjjj = jj[i]; _CheckJoint(result, jjjj.X, i, "X"); _CheckJoint(result, jjjj.Y, i, "Y"); _CheckJoint(result, jjjj.Z, i, "Z"); _CheckJoint(result, jjjj.W, i, "W"); } }
internal void ValidateWeights(Validation.ValidationContext result, int jwset) { var ww = this.AsVector4Array(); void _CheckWeight(Validation.ValidationContext r, float v, int idx, string n) { if (!v._IsReal()) { result.AddError(this, $"WEIGHTS_{jwset}[{idx}].{n} value {v} is not finite"); } if (v < 0 || v > 1) { result.AddError(this, $"WEIGHTS_{jwset}[{idx}].{n} value {v} is out of range 0-1"); } } for (int i = 0; i < ww.Count; ++i) { var wwww = ww[i]; _CheckWeight(result, wwww.X, i, "X"); _CheckWeight(result, wwww.Y, i, "Y"); _CheckWeight(result, wwww.Z, i, "Z"); _CheckWeight(result, wwww.W, i, "W"); // theoretically, the sum of all the weights should give 1, ASSUMING there's only one weight set. // but in practice, that seems not to be true. } }
internal void ValidateBounds(Validation.ValidationContext result) { if (_min.Count == 0 && _max.Count == 0) { return; } var dimensions = this.Dimensions.DimCount(); if (_min.Count != dimensions) { result.AddError(this, $"min bounds length mismatch; expected {dimensions} but found {_min.Count}"); return; } if (_max.Count != dimensions) { result.AddError(this, $"max bounds length mismatch; expected {dimensions} but found {_max.Count}"); return; } for (int i = 0; i < _min.Count; ++i) { if (_min[i] > _max[i]) { result.AddError(this, $"min[{i}] is larger than max[{i}]"); } } if (this.Encoding != EncodingType.FLOAT) { return; } var current = new float[dimensions]; var minimum = this._min.ConvertAll(item => (float)item); var maximum = this._max.ConvertAll(item => (float)item); var array = new MultiArray(this.SourceBufferView.Content, this.ByteOffset, this.Count, this.SourceBufferView.ByteStride, dimensions, this.Encoding, false); for (int i = 0; i < array.Count; ++i) { array.CopyItemTo(i, current); for (int j = 0; j < current.Length; ++j) { var v = current[j]; if (!v._IsReal()) { result.AddError(this, $"Item[{j}][{i}] is not a finite number: {v}"); } var min = minimum[j]; var max = maximum[j]; if (v < min || v > max) { result.AddError(this, $"Item[{j}][{i}] is out of bounds. {min} <= {v} <= {max}"); } } } }
internal void ValidateTangents(Validation.ValidationContext result) { var tangents = this.AsVector4Array(); for (int i = 0; i < tangents.Count; ++i) { var tgt = tangents[i]; if (!tgt._IsReal()) { result.AddError(this, $"TANGENT[{i}] value {tgt} has non finite values"); } var len = new Vector3(tgt.X, tgt.Y, tgt.Z).Length(); if (len < 0.99f || len > 1.01f) { result.AddError(this, $"TANGENT[{i}] length {len} is not unit length"); } if (tgt.W != 1 && tgt.W != -1) { result.AddError(this, $"TANGENT[{i}].W {tgt.W} has invalid value"); } } }
internal override void Validate(Validation.ValidationContext result) { base.Validate(result); // check out of range indices foreach (var idx in this._nodes) { if (idx < 0 || idx >= this.LogicalParent.LogicalNodes.Count) { result.AddError(this, $"references invalid Node[{idx}]"); } } // check duplicated indices if (this._nodes.Distinct().Count() != this._nodes.Count) { result.AddError(this, "has duplicated node references"); } }
internal void ValidateNormals(Validation.ValidationContext result) { var normals = this.AsVector3Array(); for (int i = 0; i < normals.Count; ++i) { var nrm = normals[i]; if (!nrm.IsValidNormal()) { result.AddError(this, $"NORMAL[{i}] value {nrm} is invalid"); } } }
internal void ValidatePositions(Validation.ValidationContext result) { var positions = this.AsVector3Array(); for (int i = 0; i < positions.Count; ++i) { var pos = positions[i]; if (!pos._IsReal()) { result.AddError(this, $"POSITION[{i}] value {pos} has non finite values"); } } }
internal override void Validate(Validation.ValidationContext result) { base.Validate(result); if (!_bufferView.HasValue) { result.AddError(this, $"BufferView index missing"); return; } if (_bufferView < 0 || _bufferView >= LogicalParent.LogicalBufferViews.Count) { result.AddError(this, $"BufferView index out of range"); } if (_count < _countMinimum) { result.AddError(this, $"Count is out of range"); } if (_byteOffset < 0) { result.AddError(this, $"ByteOffset is out of range"); } if (SourceBufferView.DeviceBufferTarget == BufferMode.ARRAY_BUFFER) { var len = Encoding.ByteLength() * Dimensions.DimCount(); if (len > 0 && (len & 3) != 0) { result.AddError(this, $"Expected length to be multiple of 4, found {len}"); } } if (SourceBufferView.DeviceBufferTarget == BufferMode.ELEMENT_ARRAY_BUFFER) { var len = Encoding.ByteLength() * Dimensions.DimCount(); if (len != 1 && len != 2 && len != 4) { result.AddError(this, $"Expected length to be 1, 2 or 4, found {len}"); } } }
internal void ValidateIndices(Validation.ValidationContext result, uint vertexCount, PrimitiveType drawingType) { switch (drawingType) { case PrimitiveType.LINE_LOOP: case PrimitiveType.LINE_STRIP: if (this.Count < 2) { result.AddError(this, $"Indices count {this.Count} is less than 2"); } break; case PrimitiveType.TRIANGLE_FAN: case PrimitiveType.TRIANGLE_STRIP: if (this.Count < 3) { result.AddError(this, $"Indices count {this.Count} is less than 3"); } break; case PrimitiveType.LINES: if (!this.Count.IsMultipleOf(2)) { result.AddError(this, $"Indices count {this.Count} incompatible with Primitive.{drawingType}"); } break; case PrimitiveType.TRIANGLES: if (!this.Count.IsMultipleOf(3)) { result.AddError(this, $"Indices count {this.Count} incompatible with Primitive.{drawingType}"); } break; } uint restart_value = 0xff; if (this.Encoding == EncodingType.UNSIGNED_SHORT) { restart_value = 0xffff; } if (this.Encoding == EncodingType.UNSIGNED_INT) { restart_value = 0xffffffff; } var indices = this.AsIndicesArray(); for (int i = 0; i < indices.Count; ++i) { var idx = indices[i]; if (idx == restart_value) { result.AddError(this, $"Index[{i}] value {idx} is invalid PRIMITIVE RESTART value"); } else if (idx >= vertexCount) { result.AddError(this, $"Index[{i}] value {idx} is out of range {0}-{vertexCount}"); } } }