📄 cm.java
字号:
if (t1 < -offset && t2 < -offset) { CM_RecursiveHullCheck(node.children[1], p1f, p2f, p1, p2); return; } // put the crosspoint DIST_EPSILON pixels on the near side if (t1 < t2) { idist = 1.0f / (t1 - t2); side = 1; frac2 = (t1 + offset + DIST_EPSILON) * idist; frac = (t1 - offset + DIST_EPSILON) * idist; } else if (t1 > t2) { idist = 1.0f / (t1 - t2); side = 0; frac2 = (t1 - offset - DIST_EPSILON) * idist; frac = (t1 + offset + DIST_EPSILON) * idist; } else { side = 0; frac = 1; frac2 = 0; } // move up to the node if (frac < 0) frac = 0; if (frac > 1) frac = 1; midf = p1f + (p2f - p1f) * frac; float[] mid = Vec3Cache.get(); for (i = 0; i < 3; i++) mid[i] = p1[i] + frac * (p2[i] - p1[i]); CM_RecursiveHullCheck(node.children[side], p1f, midf, p1, mid); // go past the node if (frac2 < 0) frac2 = 0; if (frac2 > 1) frac2 = 1; midf = p1f + (p2f - p1f) * frac2; for (i = 0; i < 3; i++) mid[i] = p1[i] + frac2 * (p2[i] - p1[i]); CM_RecursiveHullCheck(node.children[side ^ 1], midf, p2f, mid, p2); Vec3Cache.release(); } //====================================================================== /* * ================== CM_BoxTrace ================== */ public static trace_t BoxTrace(float[] start, float[] end, float[] mins, float[] maxs, int headnode, int brushmask) { // for multi-check avoidance checkcount++; // for statistics, may be zeroed Globals.c_traces++; // fill in a default trace //was: memset(& trace_trace, 0, sizeof(trace_trace)); trace_trace = new trace_t(); trace_trace.fraction = 1; trace_trace.surface = nullsurface.c; if (numnodes == 0) { // map not loaded return trace_trace; } trace_contents = brushmask; Math3D.VectorCopy(start, trace_start); Math3D.VectorCopy(end, trace_end); Math3D.VectorCopy(mins, trace_mins); Math3D.VectorCopy(maxs, trace_maxs); // // check for position test special case // if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2]) { int leafs[] = new int[1024]; int i, numleafs; float[] c1 = { 0, 0, 0 }, c2 = { 0, 0, 0 }; int topnode = 0; Math3D.VectorAdd(start, mins, c1); Math3D.VectorAdd(start, maxs, c2); for (i = 0; i < 3; i++) { c1[i] -= 1; c2[i] += 1; } int tn[] = { topnode }; numleafs = CM_BoxLeafnums_headnode(c1, c2, leafs, 1024, headnode, tn); topnode = tn[0]; for (i = 0; i < numleafs; i++) { CM_TestInLeaf(leafs[i]); if (trace_trace.allsolid) break; } Math3D.VectorCopy(start, trace_trace.endpos); return trace_trace; } // // check for point special case // if (mins[0] == 0 && mins[1] == 0 && mins[2] == 0 && maxs[0] == 0 && maxs[1] == 0 && maxs[2] == 0) { trace_ispoint = true; Math3D.VectorClear(trace_extents); } else { trace_ispoint = false; trace_extents[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0]; trace_extents[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1]; trace_extents[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2]; } // // general sweeping through world // CM_RecursiveHullCheck(headnode, 0, 1, start, end); if (trace_trace.fraction == 1) { Math3D.VectorCopy(end, trace_trace.endpos); } else { for (int i = 0; i < 3; i++) trace_trace.endpos[i] = start[i] + trace_trace.fraction * (end[i] - start[i]); } return trace_trace; } /* * ================== CM_TransformedBoxTrace * * Handles offseting and rotation of the end points for moving and rotating * entities ================== */ public static trace_t TransformedBoxTrace(float[] start, float[] end, float[] mins, float[] maxs, int headnode, int brushmask, float[] origin, float[] angles) { trace_t trace; float[] start_l = { 0, 0, 0 }, end_l = { 0, 0, 0 }; float[] a = { 0, 0, 0 }; float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 }, up = { 0, 0, 0 }; float[] temp = { 0, 0, 0 }; boolean rotated; // subtract origin offset Math3D.VectorSubtract(start, origin, start_l); Math3D.VectorSubtract(end, origin, end_l); // rotate start and end into the models frame of reference if (headnode != box_headnode && (angles[0] != 0 || angles[1] != 0 || angles[2] != 0)) rotated = true; else rotated = false; if (rotated) { Math3D.AngleVectors(angles, forward, right, up); Math3D.VectorCopy(start_l, temp); start_l[0] = Math3D.DotProduct(temp, forward); start_l[1] = -Math3D.DotProduct(temp, right); start_l[2] = Math3D.DotProduct(temp, up); Math3D.VectorCopy(end_l, temp); end_l[0] = Math3D.DotProduct(temp, forward); end_l[1] = -Math3D.DotProduct(temp, right); end_l[2] = Math3D.DotProduct(temp, up); } // sweep the box through the model trace = BoxTrace(start_l, end_l, mins, maxs, headnode, brushmask); if (rotated && trace.fraction != 1.0) { // FIXME: figure out how to do this with existing angles Math3D.VectorNegate(angles, a); Math3D.AngleVectors(a, forward, right, up); Math3D.VectorCopy(trace.plane.normal, temp); trace.plane.normal[0] = Math3D.DotProduct(temp, forward); trace.plane.normal[1] = -Math3D.DotProduct(temp, right); trace.plane.normal[2] = Math3D.DotProduct(temp, up); } trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]); trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]); trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]); return trace; } /* * =============================================================================== * PVS / PHS * =============================================================================== */ /* * =================== CM_DecompressVis =================== */ public static void CM_DecompressVis(byte in[], int offset, byte out[]) { int c; int row; row = (numclusters + 7) >> 3; int outp = 0; int inp = offset; if (in == null || numvisibility == 0) { // no vis info, so make all // visible while (row != 0) { out[outp++] = (byte) 0xFF; row--; } return; } do { if (in[inp] != 0) { out[outp++] = in[inp++]; continue; } c = in[inp + 1] & 0xFF; inp += 2; if (outp + c > row) { c = row - (outp); Com.DPrintf("warning: Vis decompression overrun\n"); } while (c != 0) { out[outp++] = 0; c--; } } while (outp < row); } public static byte pvsrow[] = new byte[Defines.MAX_MAP_LEAFS / 8]; public static byte phsrow[] = new byte[Defines.MAX_MAP_LEAFS / 8]; public static byte[] CM_ClusterPVS(int cluster) { if (cluster == -1) Arrays.fill(pvsrow, 0, (numclusters + 7) >> 3, (byte) 0); else CM_DecompressVis(map_visibility, map_vis.bitofs[cluster][Defines.DVIS_PVS], pvsrow); return pvsrow; } public static byte[] CM_ClusterPHS(int cluster) { if (cluster == -1) Arrays.fill(phsrow, 0, (numclusters + 7) >> 3, (byte) 0); else CM_DecompressVis(map_visibility, map_vis.bitofs[cluster][Defines.DVIS_PHS], phsrow); return phsrow; } /* * =============================================================================== * AREAPORTALS * =============================================================================== */ public static void FloodArea_r(carea_t area, int floodnum) { //Com.Printf("FloodArea_r(" + floodnum + ")...\n"); int i; qfiles.dareaportal_t p; if (area.floodvalid == floodvalid) { if (area.floodnum == floodnum) return; Com.Error(Defines.ERR_DROP, "FloodArea_r: reflooded"); } area.floodnum = floodnum; area.floodvalid = floodvalid; for (i = 0; i < area.numareaportals; i++) { p = map_areaportals[area.firstareaportal + i]; if (portalopen[p.portalnum]) FloodArea_r(map_areas[p.otherarea], floodnum); } } /* * ==================== FloodAreaConnections ==================== */ public static void FloodAreaConnections() { Com.DPrintf("FloodAreaConnections...\n"); int i; carea_t area; int floodnum; // all current floods are now invalid floodvalid++; floodnum = 0; // area 0 is not used for (i = 1; i < numareas; i++) { area = map_areas[i]; if (area.floodvalid == floodvalid) continue; // already flooded into floodnum++; FloodArea_r(area, floodnum); } } /* * ================= CM_SetAreaPortalState ================= */ public static void CM_SetAreaPortalState(int portalnum, boolean open) { if (portalnum > numareaportals) Com.Error(Defines.ERR_DROP, "areaportal > numareaportals"); portalopen[portalnum] = open; FloodAreaConnections(); } /* * ================= CM_AreasConnected ================= */ public static boolean CM_AreasConnected(int area1, int area2) { if (map_noareas.value != 0) return true; if (area1 > numareas || area2 > numareas) Com.Error(Defines.ERR_DROP, "area > numareas"); if (map_areas[area1].floodnum == map_areas[area2].floodnum) return true; return false; } /* * ================= CM_WriteAreaBits * * Writes a length byte followed by a bit vector of all the areas that area * in the same flood as the area parameter * * This is used by the client refreshes to cull visibility ================= */ public static int CM_WriteAreaBits(byte buffer[], int area) { int i; int floodnum; int bytes; bytes = (numareas + 7) >> 3; if (map_noareas.value != 0) { // for debugging, send everything Arrays.fill(buffer, 0, bytes, (byte) 255); } else { Arrays.fill(buffer, 0, bytes, (byte) 0); floodnum = map_areas[area].floodnum; for (i = 0; i < numareas; i++) { if (map_areas[i].floodnum == floodnum || area == 0) buffer[i >> 3] |= 1 << (i & 7); } } return bytes; } /* * =================== CM_WritePortalState * * Writes the portal state to a savegame file =================== */ public static void CM_WritePortalState(RandomAccessFile os) { //was: fwrite(portalopen, sizeof(portalopen), 1, f); try { for (int n = 0; n < portalopen.length; n++) if (portalopen[n]) os.writeInt(1); else os.writeInt(0); } catch (Exception e) { Com.Printf("ERROR:" + e); e.printStackTrace(); } } /* * =================== CM_ReadPortalState * * Reads the portal state from a savegame file and recalculates the area * connections =================== */ public static void CM_ReadPortalState(RandomAccessFile f) { //was: FS_Read(portalopen, sizeof(portalopen), f); int len = portalopen.length * 4; byte buf[] = new byte[len]; FS.Read(buf, len, f); ByteBuffer bb = ByteBuffer.wrap(buf); IntBuffer ib = bb.asIntBuffer(); for (int n = 0; n < portalopen.length; n++) portalopen[n] = ib.get() != 0; FloodAreaConnections(); } /* * ============= CM_HeadnodeVisible * * Returns true if any leaf under headnode has a cluster that is potentially * visible ============= */ public static boolean CM_HeadnodeVisible(int nodenum, byte visbits[]) { int leafnum; int cluster; cnode_t node; if (nodenum < 0) { leafnum = -1 - nodenum; cluster = map_leafs[leafnum].cluster; if (cluster == -1) return false; if (0 != (visbits[cluster >>> 3] & (1 << (cluster & 7)))) return true; return false; } node = map_nodes[nodenum]; if (CM_HeadnodeVisible(node.children[0], visbits)) return true; return CM_HeadnodeVisible(node.children[1], visbits); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -