public Facepoint this[int i] { get { switch (i) { case 0: return(_x); case 1: return(_y); case 2: return(_z); } return(null); } set { switch (i) { case 0: _x = value; break; case 1: _y = value; break; case 2: _z = value; break; } } }
public bool Contains(Facepoint f) { if (_x == f) { return(true); } if (_y == f) { return(true); } return(false); }
public PointTriangle(Facepoint x, Facepoint y, Facepoint z) { _x = x; _y = y; _z = z; }
public bool Contains(Facepoint f) { if (_x == f) return true; if (_y == f) return true; if (_z == f) return true; return false; }
public Facepoint this[int i] { get { switch (i) { case 0: return _x; case 1: return _y; case 2: return _z; } return null; } set { switch (i) { case 0: _x = value; break; case 1: _y = value; break; case 2: _z = value; break; } } }
//Decode a single primitive using command list public void Run(ref byte* pIn, byte** pAssets, byte** pOut, int count, PrimitiveGroup group, ref ushort* indices, IMatrixNode[] nodeTable) { //pIn is the address in the primitives //pOut is address of the face data buffers //pAssets is the address of the raw asset buffers int weight = 0; int index = 0, outSize; DecodeOp o; ElementDef* pDef; byte* p; byte[] pTexMtx = new byte[8]; byte* tIn, tOut; group._points.Add(new List<Facepoint>()); //Iterate commands in list fixed (ushort* pNode = Nodes) fixed (int* pDefData = Defs) fixed (byte* pCmd = Commands) { for (int i = 0; i < count; i++) { pDef = (ElementDef*)pDefData; p = pCmd; Facepoint f = new Facepoint(); Continue: o = (DecodeOp)(*p++); switch (o) { //Process weight using cache case DecodeOp.PosWeight: weight = pNode[*pIn++ / 3]; goto Continue; case DecodeOp.TexMtx0: case DecodeOp.TexMtx1: case DecodeOp.TexMtx2: case DecodeOp.TexMtx3: case DecodeOp.TexMtx4: case DecodeOp.TexMtx5: case DecodeOp.TexMtx6: case DecodeOp.TexMtx7: index = (int)o - (int)DecodeOp.TexMtx0; //if (*pIn++ == 0x60) //Identity matrix... // Console.WriteLine(); pTexMtx[index] = (byte)(*pIn++ / 3); goto Continue; case DecodeOp.ElementDirect: ElementCodec.Decoders[pDef->Output](ref pIn, ref pOut[pDef->Type], VQuant.DeQuantTable[pDef->Scale]); goto Continue; case DecodeOp.ElementIndexed: //Get asset index if (pDef->Format == 2) { index = *(bushort*)pIn; pIn += 2; } else index = *pIn++; switch (pDef->Type) { case 0: f._vertexIndex = index; break; case 1: f._normalIndex = index; break; case 2: case 3: f._colorIndices[pDef->Type - 2] = index; break; default: f._UVIndices[pDef->Type - 4] = index; break; } if (pDef->Type == 0) //Special processing for vertices { //Match weight and index with remap table int mapEntry = (weight << 16) | index; //Find matching index, starting at end of list //Lower index until a match is found at that index or index is less than 0 index = RemapSize; while ((--index >= 0) && (RemapTable[index] != mapEntry)) ; //No match, create new entry //Will be processed into vertices at the end! if (index < 0) { RemapTable[index = RemapSize++] = mapEntry; _points.Add(new List<Facepoint>()); } //Write index *indices++ = (ushort)index; _points[index].Add(f); } else { //Copy data from buffer outSize = pDef->Output; //Input data from asset cache tIn = pAssets[pDef->Type] + (index * outSize); tOut = pOut[pDef->Type]; if (tIn != null && tOut != null) { //Copy data to output while (outSize-- > 0) *tOut++ = *tIn++; //Increment element output pointer pOut[pDef->Type] = tOut; } } pDef++; goto Continue; default: break; //End } group._points[group._points.Count - 1].Add(f); } } }
void b_DoWork(object sender, DoWorkEventArgs e) { if (e == null) return; ObjectOptimizerForm form = e.Argument as ObjectOptimizerForm; form._newPointCount = 0; foreach (ObjectOptimization a in form._results) { if (a == null || a._object == null || a._object._manager == null || a._object._manager._triangles == null || a._facepoints == null) return; TriangleConverter triConverter = new TriangleConverter(chkUseStrips.Checked, (uint)numCacheSize.Value, (uint)numMinStripLen.Value, false, chkPushCacheHits.Checked); Facepoint[] points = new Facepoint[a._object._manager._triangles._elementCount]; uint[] indices = a._object._manager._triangles._indices; bool ccw = Collada._importOptions._forceCCW; //Indices are written in reverse for each triangle, //so they need to be set to a triangle in reverse if not CCW for (int t = 0; t < a._object._manager._triangles._elementCount; t++) points[ccw ? t : (t - (t % 3)) + (2 - (t % 3))] = a._facepoints[indices[t]]; int pc, fc; List<PrimitiveGroup> p = triConverter.GroupPrimitives(points, out pc, out fc); if (chkAllowIncrease.Checked || pc < a._pointCount) { a._pointCount = pc; a._faceCount = fc; a._groups = p; } form._newPointCount += a._pointCount; } e.Result = form; }
public FPoint(Facepoint x) { _x = x; }
public PointLine(Facepoint x, Facepoint y) { _x = x; _y = y; }
internal void WriteFacepoint(Facepoint f, PrimitiveGroup g, FacepointAttribute[] desc, ref VoidPtr address, MDL0ObjectNode node) { foreach (FacepointAttribute d in desc) switch (d._attr) { case GXAttribute.PosNrmMtxId: if (d._type == XFDataFormat.Direct) *(byte*)address++ = (byte)(3 * g._nodes.IndexOf(f.NodeID)); break; case GXAttribute.Tex0MtxId: case GXAttribute.Tex1MtxId: case GXAttribute.Tex2MtxId: case GXAttribute.Tex3MtxId: case GXAttribute.Tex4MtxId: case GXAttribute.Tex5MtxId: case GXAttribute.Tex6MtxId: case GXAttribute.Tex7MtxId: if (d._type == XFDataFormat.Direct) *(byte*)address++ = (byte)(30 + (3 * g._nodes.IndexOf(f.NodeID))); break; case GXAttribute.Position: switch (d._type) { case XFDataFormat.Direct: byte* addr = (byte*)address; node.Model._linker._vertices[node._elementIndices[0]].Write(ref addr, f._vertexIndex); address = addr; break; case XFDataFormat.Index8: *(byte*)address++ = (byte)f._vertexIndex; break; case XFDataFormat.Index16: *(bushort*)address = (ushort)f._vertexIndex; address += 2; break; } break; case GXAttribute.Normal: switch (d._type) { case XFDataFormat.Direct: byte* addr = (byte*)address; node.Model._linker._normals[node._elementIndices[1]].Write(ref addr, f._normalIndex); address = addr; break; case XFDataFormat.Index8: *(byte*)address++ = (byte)f._normalIndex; break; case XFDataFormat.Index16: *(bushort*)address = (ushort)f._normalIndex; address += 2; break; } break; case GXAttribute.Color0: case GXAttribute.Color1: switch (d._type) { case XFDataFormat.Direct: int index = (int)d._attr - 11; byte* addr = (byte*)address; node.Model._linker._colors[node._elementIndices[index + 2]].Write(ref addr, f._colorIndices[index]); address = addr; break; case XFDataFormat.Index8: if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null) *(byte*)address++ = 0; else *(byte*)address++ = (byte)f._colorIndices[(int)d._attr - 11]; break; case XFDataFormat.Index16: if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null) *(bushort*)address = 0; else *(bushort*)address = (ushort)f._colorIndices[(int)d._attr - 11]; address += 2; break; } break; case GXAttribute.Tex0: case GXAttribute.Tex1: case GXAttribute.Tex2: case GXAttribute.Tex3: case GXAttribute.Tex4: case GXAttribute.Tex5: case GXAttribute.Tex6: case GXAttribute.Tex7: switch (d._type) { case XFDataFormat.Direct: int index = (int)d._attr - 13; byte* addr = (byte*)address; node.Model._linker._uvs[node._elementIndices[index + 4]].Write(ref addr, f._UVIndices[index]); address = addr; break; case XFDataFormat.Index8: *(byte*)address++ = (byte)f._UVIndices[(int)d._attr - 13]; break; case XFDataFormat.Index16: *(bushort*)address = (ushort)f._UVIndices[(int)d._attr - 13]; address += 2; break; } break; } }
internal Facepoint[] MergeInternalFaceData(MDL0ObjectNode poly) { Facepoint[] _facepoints = new Facepoint[_pointCount]; ushort* pIndex = (ushort*)_indices.Address; for (int x = 0; x < 12; x++) { if (_faceData[x] == null && x != 0) continue; switch (x) { case 0: for (int i = 0; i < _pointCount; i++) if (_vertices.Count != 0) { Facepoint f = _facepoints[i] = new Facepoint() { _index = i }; f._vertexIndex = *pIndex++; if (f._vertexIndex < _vertices.Count && f._vertexIndex >= 0) f._vertex = _vertices[f._vertexIndex]; } break; case 1: Vector3* pIn1 = (Vector3*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) _facepoints[i]._normalIndex = Array.IndexOf(GetNormals(false), *pIn1++); break; case 2: case 3: RGBAPixel* pIn2 = (RGBAPixel*)_faceData[x].Address; if (Collada._importOptions._useOneNode) for (int i = 0; i < _pointCount; i++) _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(Collada._importOptions._singleColorNodeEntries, *pIn2++); else for (int i = 0; i < _pointCount; i++) _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(((MDL0ObjectNode)_polygon.Model._objList[_newClrObj[x - 2]])._manager.GetColors(x - 2, false), *pIn2++); break; default: Vector2* pIn3 = (Vector2*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) _facepoints[i]._UVIndices[x - 4] = Array.IndexOf(GetUVs(x - 4, false), *pIn3++); break; } } return _facepoints; }
internal Facepoint[] MergeExternalFaceData(MDL0ObjectNode poly) { Facepoint[] _facepoints = new Facepoint[_pointCount]; ushort* pIndex = (ushort*)_indices.Address; for (int x = 0; x < 12; x++) { if (poly._elementIndices[x] < 0 && x != 0) continue; switch (x) { case 0: Vector3* pIn0 = (Vector3*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) { Facepoint f = _facepoints[i] = new Facepoint() { _index = i }; if (_vertices.Count != 0) { ushort id = *pIndex++; if (id < _vertices.Count && id >= 0) f._vertex = _vertices[id]; f._vertexIndex = f._vertex._facepoints[0]._vertexIndex; } } break; case 1: Vector3* pIn1 = (Vector3*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) _facepoints[i]._normalIndex = Array.IndexOf(poly._normalNode.Normals, *pIn1++); break; case 2: case 3: RGBAPixel* pIn2 = (RGBAPixel*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(poly._colorSet[x - 2].Colors, *pIn2++); break; default: Vector2* pIn3 = (Vector2*)_faceData[x].Address; for (int i = 0; i < _pointCount; i++) _facepoints[i]._UVIndices[x - 4] = Array.IndexOf(poly._uvSet[x - 4].Points, *pIn3++); break; } } return _facepoints; }
//This should be done after node indices have been assigned public override int OnCalculateSize(bool force) { //Reset everything! _tableLen = _primitiveStart = _primitiveSize = _fpStride = 0; MDL0Node model = Model; if (model._isImport) { //Continue checking for single bind if (_nodeId == -2 && _matrixNode == null) { bool first = true; foreach (Vertex3 v in _manager._vertices) { if (first) { if (v._matrixNode != null) MatrixNode = model._linker.NodeCache[v._matrixNode.NodeIndex]; first = false; } v.MatrixNode = null; } } } //Collect vertex node ids GenerateNodeCache(); //Recollect indices of linked nodes RecalcIndices(); //Check that the facepoint descriptor matches the linked nodes if (!_rebuild) _rebuild = CheckVertexFormat(); //Rebuild only under certain circumstances if (model._rebuildAllObj || model._isImport || _rebuild || _reOptimized) { int size = (int)MDL0Object.Size; if (model._version >= 10) size += 4; //Add extra -1 value //Set vertex descriptor _descList = _manager.SetVertexDescList(this, model._linker._forceDirectAssets); //Add table length size += _nodeCache.Length * 2 + 4; _tableLen = ((size.Align(0x10) + 0xE0) % 0x20 == 0) ? size.Align(0x10) : size.Align(0x20); //Add def length size = _primitiveStart = _tableLen + 0xE0; //Need to group facepoint data if creating a new model if (model._isImport) { _triConverter._useStrips = Collada._importOptions._useTristrips; _triConverter._cacheSize = Collada._importOptions._cacheSize; _triConverter._minStripLen = Collada._importOptions._minStripLen; _triConverter._pushCacheHits = Collada._importOptions._pushCacheHits; _triConverter._backwardSearch = Collada._importOptions._backwardSearch; _primGroups.Clear(); //Merge vertices and assets into facepoints Facepoint[] facepoints = _manager.MergeInternalFaceData(this); if (_manager._triangles != null) { Facepoint[] points = new Facepoint[_manager._triangles._elementCount]; uint[] indices = _manager._triangles._indices; bool ccw = Collada._importOptions._forceCCW; //Indices are written in reverse for each triangle, //so they need to be set to a triangle in reverse if not CCW for (int t = 0; t < _manager._triangles._elementCount; t++) points[ccw ? t : (t - (t % 3)) + (2 - (t % 3))] = facepoints[indices[t]]; _primGroups = _triConverter.GroupPrimitives(points, out _numFacepoints, out _numFaces); } } //Build display list foreach (PrimitiveGroup g in _primGroups) { if (model._isImport || _reOptimized) { if (g._tristrips.Count != 0) foreach (PointTriangleStrip strip in g._tristrips) _primitiveSize += 3 + strip._points.Count * _fpStride; if (g._triangles.Count != 0) _primitiveSize += 3 + g._triangles.Count * 3 * _fpStride; } else for (int i = 0; i < g._headers.Count; i++) _primitiveSize += 3 + g._points[i].Count * _fpStride; if (Weighted) _primitiveSize += 5 * g._nodes.Count * (HasTexMtx ? 3 : 2); //Add total matrices size } size += _primitiveSize; int align = ((size.Align(0x10)) % 0x20 == 0) ? 0x10 : 0x20; size = size.Align(align); _primitiveSize = _primitiveSize.Align(align); //Texture matrices (0x30) start at 0x00, max 11 //Pos matrices (0x20) start at 0x78, max 10 //Normal matrices (0x28) start at 0x400, max 10 return size; } else return base.OnCalculateSize(force); }