/// <summary> /// Calculate the polygon normals. By convention, LW's polygon normals /// are found as the cross product of the first and last edges. It's /// undefined for one- and two-point polygons. /// </summary> /// <param name="lwPolygonList"></param> public void GetPolyNormals(ref lwPolygonList polygon) { float[] p1 = new float[3]; float[] p2 = new float[3]; float[] pn = new float[3]; float[] v1 = new float[3]; float[] v2 = new float[3]; for (int i = 0; i < polygon.count; i++) { if (polygon.pol[i].nverts < 3) { continue; } for (int j = 0; j < 3; j++) { p1[j] = pt[polygon.pol[i].v[0].index].pos[j]; p2[j] = pt[polygon.pol[i].v[1].index].pos[j]; pn[j] = pt[polygon.pol[i].v[polygon.pol[i].nverts - 1].index].pos[j]; } for (int j = 0; j < 3; j++) { v1[j] = p2[j] - p1[j]; v2[j] = pn[j] - p1[j]; } LwVecMath.cross(v1, v2, polygon.pol[i].norm); LwVecMath.normalize(polygon.pol[i].norm); } }
/// <summary> /// Calculate the vertex normals. For each polygon vertex, sum the /// normals of the polygons that share the point. If the normals of the /// current and adjacent polygons form an angle greater than the max /// smoothing angle for the current polygon's surface, the normal of the /// adjacent polygon is excluded from the sum. It's also excluded if the /// polygons aren't in the same smoothing group. /// /// Assumes that lwGetPointPolygons(), lwGetPolyNormals() and /// lwResolvePolySurfaces() have already been called. /// </summary> /// <param name="lwPolygonList"></param> public void GetVertNormals(ref lwPolygonList polygon) { int h, p; float a; for (int j = 0; j < polygon.count; j++) { for (int n = 0; n < polygon.pol[j].nverts; n++) { for (int k = 0; k < 3; k++) { polygon.pol[j].v[n].norm[k] = polygon.pol[j].norm[k]; } if (polygon.pol[j].surf.smooth <= 0) { continue; } p = polygon.pol[j].v[n].index; for (int g = 0; g < pt[p].npols; g++) { h = pt[p].pol[g]; if (h == j) { continue; } if (polygon.pol[j].smoothgrp != polygon.pol[h].smoothgrp) { continue; } a = LwVecMath.vecangle(polygon.pol[j].norm, polygon.pol[h].norm); if (a > polygon.pol[j].surf.smooth) { continue; } for (int k = 0; k < 3; k++) { polygon.pol[j].v[n].norm[k] += polygon.pol[h].norm[k]; } } LwVecMath.normalize(polygon.pol[j].v[n].norm); } } }
/// <summary> /// For each point, fill in the indexes of the polygons that share the /// point. Returns false if any of the memory allocations fail, otherwise /// returns true. /// </summary> /// <param name="lwPolygonList"></param> /// <returns></returns> public bool GetPointPolygons(ref lwPolygonList polygon) { int k; /* count the number of polygons per point */ for (int i = 0; i < polygon.count; i++) { for (int j = 0; j < polygon.pol[i].nverts; j++) { ++pt[polygon.pol[i].v[j].index].npols; } } /* alloc per-point polygon arrays */ for (int i = 0; i < count; i++) { if (pt[i].npols == 0) { continue; } pt[i].pol = new int[pt[i].npols]; if (pt[i].pol == null) { return(false); } pt[i].npols = 0; } /* fill in polygon array for each point */ for (int i = 0; i < polygon.count; i++) { for (int j = 0; j < polygon.pol[i].nverts; j++) { k = polygon.pol[i].v[j].index; pt[k].pol[pt[k].npols] = i; ++pt[k].npols; } } return(true); }
/// <summary> /// Calculate the polygon normals. By convention, LW's polygon normals /// are found as the cross product of the first and last edges. It's /// undefined for one- and two-point polygons. /// </summary> /// <param name="lwPolygonList"></param> public void GetPolyNormals(ref lwPolygonList polygon) { float[] p1 = new float[3]; float[] p2 = new float[3]; float[] pn = new float[3]; float[] v1 = new float[3]; float[] v2 = new float[3]; for (int i = 0; i < polygon.count; i++) { if (polygon.pol[i].nverts < 3) continue; for (int j = 0; j < 3; j++) { p1[j] = pt[polygon.pol[i].v[0].index].pos[j]; p2[j] = pt[polygon.pol[i].v[1].index].pos[j]; pn[j] = pt[polygon.pol[i].v[polygon.pol[i].nverts - 1].index].pos[j]; } for (int j = 0; j < 3; j++) { v1[j] = p2[j] - p1[j]; v2[j] = pn[j] - p1[j]; } LwVecMath.cross(v1, v2, polygon.pol[i].norm); LwVecMath.normalize(polygon.pol[i].norm); } }
/// <summary> /// Calculate the vertex normals. For each polygon vertex, sum the /// normals of the polygons that share the point. If the normals of the /// current and adjacent polygons form an angle greater than the max /// smoothing angle for the current polygon's surface, the normal of the /// adjacent polygon is excluded from the sum. It's also excluded if the /// polygons aren't in the same smoothing group. /// /// Assumes that lwGetPointPolygons(), lwGetPolyNormals() and /// lwResolvePolySurfaces() have already been called. /// </summary> /// <param name="lwPolygonList"></param> public void GetVertNormals(ref lwPolygonList polygon) { int h, p; float a; for (int j = 0; j < polygon.count; j++) { for (int n = 0; n < polygon.pol[j].nverts; n++) { for (int k = 0; k < 3; k++) polygon.pol[j].v[n].norm[k] = polygon.pol[j].norm[k]; if (polygon.pol[j].surf.smooth <= 0) continue; p = polygon.pol[j].v[n].index; for (int g = 0; g < pt[p].npols; g++) { h = pt[p].pol[g]; if (h == j) continue; if (polygon.pol[j].smoothgrp != polygon.pol[h].smoothgrp) continue; a = LwVecMath.vecangle(polygon.pol[j].norm, polygon.pol[h].norm); if (a > polygon.pol[j].surf.smooth) continue; for (int k = 0; k < 3; k++) polygon.pol[j].v[n].norm[k] += polygon.pol[h].norm[k]; } LwVecMath.normalize(polygon.pol[j].v[n].norm); } } }
/// <summary> /// For each point, fill in the indexes of the polygons that share the /// point. Returns false if any of the memory allocations fail, otherwise /// returns true. /// </summary> /// <param name="lwPolygonList"></param> /// <returns></returns> public bool GetPointPolygons(ref lwPolygonList polygon) { int k; /* count the number of polygons per point */ for (int i = 0; i < polygon.count; i++) for (int j = 0; j < polygon.pol[i].nverts; j++) ++pt[polygon.pol[i].v[j].index].npols; /* alloc per-point polygon arrays */ for (int i = 0; i < count; i++) { if (pt[i].npols == 0) continue; pt[i].pol = new int[pt[i].npols]; if (pt[i].pol == null) return false; pt[i].npols = 0; } /* fill in polygon array for each point */ for (int i = 0; i < polygon.count; i++) { for (int j = 0; j < polygon.pol[i].nverts; j++) { k = polygon.pol[i].v[j].index; pt[k].pol[pt[k].npols] = i; ++pt[k].npols; } } return true; }
/// <summary> /// Read polygon records from a POLS chunk in an LWO2 file. The polygons /// are added to the array in the lwPolygonList. /// </summary> public bool GetPolygons(FileStream fp, int cksize, ref lwPolygonList plist, int ptoffset) { BinaryReader read = new BinaryReader(fp); int pp; lwPolVert pv; byte[] buf; int bp; int j, flags, nv, nverts, npols; uint type; if (cksize == 0) { return(true); } /* read the whole chunk */ int flen = 0; type = lwio.getU4(read, ref flen); buf = lwio.getbytes(read, cksize - 4, ref flen); if (cksize != flen) { goto Fail; } /* count the polygons and vertices */ nverts = 0; npols = 0; bp = 0; while (bp < cksize - 4) { nv = lwio.sgetU2(buf, ref bp, ref flen); nv &= 0x03FF; nverts += nv; npols++; for (int i = 0; i < nv; i++) { ; } j = lwio.sgetVX(buf, ref bp, ref flen); } AllocPolygons(npols, nverts); /* fill in the new polygons */ bp = 0; pp = plist.offset; pv = plist.pol[0].v[plist.voffset]; for (int i = 0; i < npols; i++) { nv = lwio.sgetU2(buf, ref bp, ref flen); flags = nv & 0xFC00; nv &= 0x03FF; plist.pol[pp].nverts = nv; plist.pol[pp].flags = flags; plist.pol[pp].type = type; //if (plist.pol[pp].v == null) // plist.pol[pp].v = pv; //for (int j = 0; j < nv; j++) // plist.pol[pp].v[j].index = lwio.sgetVX(buf, ref bp, ref flen) + ptoffset; pp++; //pv += nv; } return(true); Fail: return(false); }
/// <summary> /// Read polygon records from a POLS chunk in an LWO2 file. The polygons /// are added to the array in the lwPolygonList. /// </summary> public bool GetPolygons(FileStream fp, int cksize, ref lwPolygonList plist, int ptoffset) { BinaryReader read = new BinaryReader(fp); int pp; lwPolVert pv; byte[] buf; int bp; int j, flags, nv, nverts, npols; uint type; if (cksize == 0) return true; /* read the whole chunk */ int flen = 0; type = lwio.getU4(read, ref flen); buf = lwio.getbytes(read, cksize - 4, ref flen); if (cksize != flen) goto Fail; /* count the polygons and vertices */ nverts = 0; npols = 0; bp = 0; while (bp < cksize - 4) { nv = lwio.sgetU2(buf, ref bp, ref flen); nv &= 0x03FF; nverts += nv; npols++; for (int i = 0; i < nv; i++) ; j = lwio.sgetVX(buf, ref bp, ref flen); } AllocPolygons(npols, nverts); /* fill in the new polygons */ bp = 0; pp = plist.offset; pv = plist.pol[0].v[plist.voffset]; for (int i = 0; i < npols; i++) { nv = lwio.sgetU2(buf, ref bp, ref flen); flags = nv & 0xFC00; nv &= 0x03FF; plist.pol[pp].nverts = nv; plist.pol[pp].flags = flags; plist.pol[pp].type = type; //if (plist.pol[pp].v == null) // plist.pol[pp].v = pv; //for (int j = 0; j < nv; j++) // plist.pol[pp].v[j].index = lwio.sgetVX(buf, ref bp, ref flen) + ptoffset; pp++; //pv += nv; } return true; Fail: return false; }