3d点云球

aarongod 3天前 121


import win.ui;
/*DSG{{*/
var winform = win.form(text="点云球";right=639;bottom=479;bgcolor=0)
winform.add(
plus={cls="plus";left=0;top=0;right=640;bottom=480;db=1;dl=1;dr=1;dt=1;z=1}
);
/*}}*/
import gdip;
import gdip.graphics;

// --- 配置参数 ---
var MAXPOINT = 2888; // 点数过多会导致 GDI+ 绘图频率下降,1200点较平衡
var PI = 3.1415926536;
var viewZ = 3.0;     // 视点深度

var p3d = {};
math.randomize();

// 1. 初始化球面随机点
var initPoint = function(){
    for(i=1; MAXPOINT; 1){
        var z = 2.0 * math.random() - 1; 
        var rxy = math.sqrt(1 - z * z); 
        var a = 2 * PI * math.random(); 

        table.push(p3d, {
            x = math.cos(a) * rxy;
            y = math.sin(a) * rxy;
            z = z;
        })
    }
}

// 2. 旋转逻辑
var rotateAll = function(){
    // 绕三个轴小幅度旋转弧度
    var ax, ay, az = PI/800, PI/600, PI/400;
    var cosX, sinX = math.cos(ax), math.sin(ax);
    var cosY, sinY = math.cos(ay), math.sin(ay);
    var cosZ, sinZ = math.cos(az), math.sin(az);

    for(i=1; #p3d; 1){
        var p = p3d[i];

        // X轴旋转
        var y = p.y;
        p.y = y * cosX - p.z * sinX;
        p.z = y * sinX + p.z * cosX;

        // Y轴旋转
        var x = p.x;
        p.x = x * cosY + p.z * sinY;
        p.z = -x * sinY + p.z * cosY;

        // Z轴旋转
        x = p.x;
        p.x = x * cosZ - p.y * sinZ;
        p.y = x * sinZ + p.y * cosZ;
    }

    // 关键:旋转后立即排序(画家算法),解决遮挡关系
    table.sort(p3d, lambda(next) owner.z < next.z);
}

initPoint();

// 3. 绘图回调 (只负责渲染)
// 规范:参数依次为 (graphics, rc, txtColor, rcContent, foreColor)
winform.plus.onDrawContent = function(graphics, rc) {
    graphics.smoothingMode = 4/*_GdipSmoothingModeAntiAlias*/;

    var centerX = rc.width() / 2;
    var centerY = rc.height() / 2;

    for(i=1; #p3d; 1){
        var p = p3d[i];

        // 透视投影计算
        var factor = viewZ / (viewZ - p.z);
        var screenX = (p.x * factor * 220) + centerX;
        var screenY = (p.y * factor * 220) + centerY;

        // 颜色深度计算 (z 范围 -1 到 1)
        var brightness = math.floor((p.z + 1) * 100) + 55; // 55~255

        var r = brightness;
        var g = math.floor(brightness * 0.1); 
        var b = math.floor(brightness * 0.6);
        var alpha = math.floor((p.z + 1) * 75) + 100; // 100~250

        // 构造 ARGB 颜色
        var argb = (alpha << 24) | (r << 16) | (g << 8) | b;

        // 创建画刷并绘制
        var brush = gdip.solidBrush(argb);
        var dotSize = 1.5 * factor; 

        // 修正:直接调用成员方法,不建议缓存函数
        graphics.fillEllipse(brush, screenX - dotSize/2, screenY - dotSize/2, dotSize, dotSize);

        // 必须及时删除画刷,防止内存泄漏
        brush.delete();
    }
}

// 4. 定时刷新逻辑
winform.setInterval( 
    function(){
        rotateAll(); // 在计时器中处理逻辑
        winform.plus.redraw(); // 触发绘图回调
    }, 15 
)

// 设置控件属性
winform.plus.background = 0xFF000000; // 背景黑
winform.plus.foreground = 0x00000000; // 前景透

winform.show();
win.loopMessage();


最新回复 (1)
  • mfk 3天前
    0 2

返回