Files
ViewpointTurrets/source/localmods/mtkviewpoint/TracerMesh.java
T
2026-10-27 17:16:21 -04:00

39 lines
1.7 KiB
Java

package localmods.mtkviewpoint;
import java.nio.FloatBuffer;
import org.joml.Matrix4f;
import org.joml.Vector4f;
/** Projected ribbons retain world depth; clipping prevents flashes behind the camera. */
public final class TracerMesh {
public record Segment(float hx,float hy,float hz,float tx,float ty,float tz,float r,float g,float b,float alpha) {}
public static final int STRIDE=10;
private TracerMesh() {}
public static int append(FloatBuffer out, Segment s, Matrix4f vp, int width, int height) {
if (width<=0 || height<=0 || out.remaining()<6*STRIDE) return 0;
var h=vp.transform(new Vector4f(s.hx,s.hy,s.hz,1));
var t=vp.transform(new Vector4f(s.tx,s.ty,s.tz,1));
if (!h.isFinite() || !t.isFinite()) return 0;
float hn=h.z+h.w, tn=t.z+t.w;
if (hn<=0 && tn<=0) return 0;
if (hn<=0) h.lerp(t,(-hn+0.00001f)/(tn-hn));
else if (tn<=0) t.lerp(h,(-tn+0.00001f)/(hn-tn));
if (h.w<=0.000001f || t.w<=0.000001f) return 0;
float dx=(h.x/h.w-t.x/t.w)*width, dy=(h.y/h.w-t.y/t.w)*height;
float len=(float)Math.hypot(dx,dy);
if (len<1) { // End-on rounds still have a small visible core.
t.x-=4f/width*t.w; dx=4; dy=0; len=4;
}
float ox=-dy/len*2.5f/width, oy=dx/len*2.5f/height;
vertex(out,t,ox,oy,-1,0,s); vertex(out,h,ox,oy,-1,1,s); vertex(out,h,ox,oy,1,1,s);
vertex(out,t,ox,oy,-1,0,s); vertex(out,h,ox,oy,1,1,s); vertex(out,t,ox,oy,1,0,s);
return 6;
}
private static void vertex(FloatBuffer b,Vector4f p,float ox,float oy,float side,float along,Segment s) {
b.put(p.x+ox*side*p.w).put(p.y+oy*side*p.w).put(p.z).put(p.w);
b.put(along).put(side).put(s.r).put(s.g).put(s.b).put(s.alpha);
}
}