"CandyCAD.MainWindow"

OpenTK 2026-05-07 17:45:38

<Window x:Class="CandyCAD.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CandyCAD"
        Title="CandyCAD - 3D Viewer" 
        Height="600" Width="900"
        Loaded="Window_Loaded"
        Closing="Window_Closing">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- 左侧控制面板 -->
        <Border Grid.Column="0" Background="#2A2A2A" BorderBrush="#444" BorderThickness="0,0,1,0">
            <StackPanel Margin="10">

                <TextBlock Text="CandyCAD" FontSize="18" FontWeight="Bold" Foreground="#F0D84C" 
                           HorizontalAlignment="Center" Margin="0,0,0,15"/>

                <Border Background="#3A3A3A" CornerRadius="4" Padding="8" Margin="0,0,0,10">
                    <StackPanel>
                        <TextBlock Text="当前场景" Foreground="#CCC" FontWeight="Bold" Margin="0,0,0,5"/>
                        <TextBlock x:Name="SceneInfo" Text="立方体" Foreground="#888" FontSize="11"/>
                        <TextBlock x:Name="VertexInfo" Text="顶点: 36" Foreground="#888" FontSize="11"/>
                        <TextBlock x:Name="TriangleInfo" Text="三角形: 12" Foreground="#888" FontSize="11"/>
                    </StackPanel>
                </Border>

                <GroupBox Header="相机控制" Foreground="#CCC" Margin="0,0,0,10">
                    <StackPanel>
                        <Button x:Name="ResetCameraBtn" Content="重置相机" Height="30" Margin="0,3" 
                                Click="ResetCamera_Click" Background="#4A6A8A" Foreground="White" BorderThickness="0"/>
                        <Button x:Name="FitViewBtn" Content="适应视图" Height="30" Margin="0,3" 
                                Click="FitView_Click" Background="#4A6A8A" Foreground="White" BorderThickness="0"/>
                    </StackPanel>
                </GroupBox>

                <GroupBox Header="模型变换" Foreground="#CCC" Margin="0,0,0,10">
                    <StackPanel>
                        <Slider x:Name="RotateSlider" Minimum="0" Maximum="360" Value="45" 
                                TickFrequency="45" TickPlacement="BottomRight"
                                ValueChanged="RotateSlider_Changed"/>
                        <TextBlock Text="旋转角度" Foreground="#AAA" FontSize="11" HorizontalAlignment="Center"/>

                        <Slider x:Name="ScaleSlider" Minimum="0.5" Maximum="2.0" Value="1.0" 
                                TickFrequency="0.25" TickPlacement="BottomRight" Margin="0,10,0,0"
                                ValueChanged="ScaleSlider_Changed"/>
                        <TextBlock Text="缩放" Foreground="#AAA" FontSize="11" HorizontalAlignment="Center"/>
                    </StackPanel>
                </GroupBox>

                <GroupBox Header="渲染设置" Foreground="#CCC" Margin="0,0,0,10">
                    <StackPanel>
                        <CheckBox x:Name="WireframeCheckBox" Content="线框模式" Foreground="#DDD" Margin="0,3" 
                                  Checked="WireframeMode_Changed" Unchecked="WireframeMode_Changed"/>
                        <CheckBox x:Name="GridCheckBox" Content="显示网格" Foreground="#DDD" Margin="0,3" 
                                  IsChecked="True" Checked="GridMode_Changed" Unchecked="GridMode_Changed"/>
                    </StackPanel>
                </GroupBox>

                <TextBlock x:Name="InfoText" Text="鼠标拖拽旋转视图" Foreground="#888" FontSize="11" 
                           HorizontalAlignment="Center" Margin="0,10,0,0"/>

                <TextBlock x:Name="FpsText" Text="FPS: --" Foreground="#F0D84C" FontSize="12" 
                           HorizontalAlignment="Center" Margin="0,10,0,0"/>
            </StackPanel>
        </Border>

        <!-- 右侧渲染区域 -->
        <Border Grid.Column="1" Background="#1E1E1E">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="25"/>
                </Grid.RowDefinitions>

                <!-- OpenGL 渲染视图 -->
                <Border Grid.Column="1" Background="#1E1E1E" Margin="5">
                    <WindowsFormsHost x:Name="host">
                        <local:OpenGLControl x:Name="glView" 
                             BackColor="#1E1E1E" 
                             Dock="Fill" 
                             MinimumSize="400,300" />
                    </WindowsFormsHost>
                </Border>

                <!-- 状态栏 -->
                <StatusBar Grid.Row="1" Background="#2A2A2A">
                    <StatusBarItem>
                        <TextBlock x:Name="StatusText" Text="就绪" Foreground="#888"/>
                    </StatusBarItem>
                    <Separator/>
                    <StatusBarItem>
                        <TextBlock x:Name="CameraPosText" Text="相机: (0, 0, 5)" Foreground="#888"/>
                    </StatusBarItem>
                    <Separator/>
                    <StatusBarItem>
                        <TextBlock x:Name="MousePosText" Text="鼠标: (0, 0)" Foreground="#888"/>
                    </StatusBarItem>
                </StatusBar>
            </Grid>
        </Border>
    </Grid>
</Window>

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace CandyCAD
{
    public partial class MainWindow : Window
    {
        private int frameCount = 0;
        private DateTime lastTime = DateTime.Now;
        private System.Windows.Point lastMousePos;
        private bool isMouseDown = false;

        public MainWindow()
        {
            InitializeComponent();

            // 在 glView 上直接订阅鼠标事件(WinForms 事件)
            glView.MouseDown += OnGlViewMouseDown;
            glView.MouseMove += OnGlViewMouseMove;
            glView.MouseUp += OnGlViewMouseUp;
            glView.MouseWheel += OnGlViewMouseWheel;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CompositionTarget.Rendering += OnRendering;

            if (StatusText != null)
                StatusText.Text = "CandyCAD 已启动 | 左键旋转 | 右键平移 | 滚轮缩放";
        }

        private void OnRendering(object sender, EventArgs e)
        {
            if (glView != null)
            {
                RenderInterop.RenderFrame();
            }

            frameCount++;
            var now = DateTime.Now;
            if ((now - lastTime).TotalSeconds >= 1)
            {
                if (FpsText != null)
                    FpsText.Text = $"FPS: {frameCount}";
                frameCount = 0;
                lastTime = now;
            }

            RenderInterop.GetCameraPosition(out float x, out float y, out float z);
            if (CameraPosText != null)
                CameraPosText.Text = $"相机: ({x:F1}, {y:F1}, {z:F1})";
        }

        // ===== WinForms 鼠标事件(直接使用 glView)=====
        private void OnGlViewMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            lastMousePos = new System.Windows.Point(e.X, e.Y);
            isMouseDown = true;
            glView.Capture = true;  // WinForms 的 Capture 属性

            if (StatusText != null)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                    StatusText.Text = "旋转视图 (左键拖拽)";
                else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                    StatusText.Text = "平移视图 (右键拖拽)";
            }
        }

        private void OnGlViewMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!isMouseDown) return;

            double dx = e.X - lastMousePos.X;
            double dy = e.Y - lastMousePos.Y;

            if (MousePosText != null)
                MousePosText.Text = $"鼠标: ({e.X}, {e.Y})";

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                RenderInterop.ProcessMouseMovement((float)dx, (float)dy);
            }
            else if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                RenderInterop.ProcessPan((float)dx, (float)dy);
            }

            lastMousePos = new System.Windows.Point(e.X, e.Y);
        }

        private void OnGlViewMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            isMouseDown = false;
            glView.Capture = false;  // WinForms 的 Capture 属性

            if (StatusText != null)
                StatusText.Text = "就绪 | 左键旋转 | 右键平移 | 滚轮缩放";
        }

        private void OnGlViewMouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            float delta = e.Delta > 0 ? 1.0f : -1.0f;
            RenderInterop.ProcessMouseScroll(delta);

            if (StatusText != null)
                StatusText.Text = e.Delta > 0 ? "放大" : "缩小";
        }

        // ===== 按钮事件 =====
        private void ResetCamera_Click(object sender, RoutedEventArgs e)
        {
            RenderInterop.ResetCamera();
            if (StatusText != null)
                StatusText.Text = "相机已重置";
        }

        private void FitView_Click(object sender, RoutedEventArgs e)
        {
            RenderInterop.FitView();
            if (StatusText != null)
                StatusText.Text = "适应视图";
        }

        private void RotateSlider_Changed(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            float angle = (float)e.NewValue;
            RenderInterop.SetModelRotation(angle, angle, 0);
            if (InfoText != null)
                InfoText.Text = $"旋转角度: {angle:F0}°";
        }

        private void ScaleSlider_Changed(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            float scale = (float)e.NewValue;
            RenderInterop.SetModelScale(scale);
            if (InfoText != null)
                InfoText.Text = $"缩放: {scale:F2}";
        }

        private void WireframeMode_Changed(object sender, RoutedEventArgs e)
        {
            bool enabled = WireframeCheckBox.IsChecked == true;
            RenderInterop.SetWireframeMode(enabled);
            if (StatusText != null)
                StatusText.Text = enabled ? "线框模式" : "实体模式";
        }

        private void GridMode_Changed(object sender, RoutedEventArgs e)
        {
            bool show = GridCheckBox.IsChecked == true;
            RenderInterop.ShowGrid(show);
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            RenderInterop.Shutdown();
        }
    }
}

using System;
using System.Windows.Forms;

namespace CandyCAD
{
    public class OpenGLControl : Control
    {

        public OpenGLControl()
        {
            SetStyle(ControlStyles.EnableNotifyMessage, true);
            this.MouseWheel += (s, e) => { };
        }
        private bool isInitialized = false;

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);

            System.Diagnostics.Debug.WriteLine("=== OnHandleCreated called ===");
            System.Diagnostics.Debug.WriteLine($"Handle: {this.Handle}, Width: {this.Width}, Height: {this.Height}");

            if (!isInitialized && this.IsHandleCreated && this.Width > 0 && this.Height > 0)
            {
                System.Diagnostics.Debug.WriteLine("Calling RenderInterop.Initialize...");
                bool result = RenderInterop.Initialize(this.Handle, this.Width, this.Height);
                System.Diagnostics.Debug.WriteLine($"RenderInterop.Initialize returned: {result}");

                if (!result)
                    throw new Exception("Failed to initialize OpenGL renderer");

                isInitialized = true;
                System.Diagnostics.Debug.WriteLine("OpenGL initialized successfully");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Skipping initialization - conditions not met");
                System.Diagnostics.Debug.WriteLine($"isInitialized: {isInitialized}");
                System.Diagnostics.Debug.WriteLine($"IsHandleCreated: {this.IsHandleCreated}");
                System.Diagnostics.Debug.WriteLine($"Width: {this.Width}, Height: {this.Height}");
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (isInitialized && this.Width > 0 && this.Height > 0)
            {
                RenderInterop.Resize(this.Width, this.Height);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (isInitialized)
                RenderInterop.RenderFrame();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && isInitialized)
                RenderInterop.Shutdown();
            base.Dispose(disposing);
        }
    }
}

using System;
using System.Runtime.InteropServices;

namespace CandyCAD
{
    public static class RenderInterop
    {
        private const string DllName = "CandyRenderEngine.dll";

        // 基础渲染
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool Initialize(IntPtr hwnd, int width, int height);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void Shutdown();

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void RenderFrame();

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void Resize(int width, int height);

        // 相机控制
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ProcessMouseMovement(float xOffset, float yOffset);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ProcessMouseScroll(float yOffset);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ProcessPan(float xOffset, float yOffset);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ResetCamera();

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void FitView();

        // 模型变换
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetModelRotation(float x, float y, float z);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetModelScale(float scale);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetModelPosition(float x, float y, float z);

        // 渲染设置
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetWireframeMode(bool enabled);

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void ShowGrid(bool show);

        // 获取信息
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern void GetCameraPosition(out float x, out float y, out float z);
        // 添加到 RenderInterop.cs 中

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool GetWireframeMode();

        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern bool IsGridVisible();
    }
}

...全文
326 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文系统研究了基于W-GAN(Wasserstein生成对抗网络)的光伏出力场景生成方法,并提供了完整的Python代码实现。该方法充分利用W-GAN在捕捉复杂数据分布方面的优势,能够生成具有高度真实性与时序一致性的光伏发电功率场景,有效解决了传统场景生成方法在处理非线性、非平稳光伏数据时存在的模式坍塌与分布偏差问题。研究内容涵盖网络架构设计、梯度惩罚机制引入以保障训练稳定性、损失函数优化及生成样本质量评估等关键环节,生成的场景可用于电力系统规划、运行调度、储能配置及风险评估等任务,尤其适用于高比例可再生能源接入背景下的不确定性建模需求。; 适合人群:具备一定Python编程能力、深度学习基础理论知识的研究生、科研人员,以及从事新能源发电预测、电力系统优化调度等相关领域的工程技术人员。; 使用场景及目标:①实现光伏出力不确定性建模,生成满足统计特性的典型与极端功率场景;②支撑含光伏的微电网、主动配电网的优化调度、可靠性分析与韧性评估;③作为深度学习在能源时序数据生成领域的一个典型案例,服务于教学演示与学术研究。; 阅读建议:建议结合所提供的Python代码进行动手实践,重点理解W-GAN中判别器(Critic)结构、梯度惩罚项(Gradient Penalty)的实现原理,并通过可视化手段对比原始数据与生成数据的分布特征,进一步可尝试将其与传统GAN、VAE或DDPM等生成模型在场景多样性、保真度方面进行横向比较。
代码转载自:https://pan.quark.cn/s/a4b39357ea24 **C#反编译工具dnSpy的详细说明** dnSpy是一款专门用于C#编程语言的强效反编译器,其具备广泛的功能,涵盖了反编译、调试以及代码编辑等多个方面。这款工具凭借其便捷的操作性和丰富的特性,广泛受到开发者和逆向工程从业者的青睐。本文将详细研究dnSpy的关键功能、运作机制以及其在软件开发中的实际应用。 dnSpy的关键功能之一是反编译。它能够将已编译的.NET程序集(例如DLL或EXE文件)还原为源代码形态,从而让开发者得以审视并掌握应用程序的内部构造。借助IL(中间语言)反编译技术,dnSpy能够生成与原始C#代码高度相似的代码,以便用户进行阅读和分析。不仅如此,dnSpy还兼容其他.NET语言,例如VB.NET和F#。 dnSpy的调试功能是其另一显著优势。它内含了一个功能强大的调试器,使用户可以在反编译后的代码中设置断点,检查并调整变量值,以及追踪代码的执行路径等。这对于故障排除、学习他人代码或进行安全研究都极具帮助。同时,dnSpy支持模块和程序集的热替换,即在调试期间可以即时更新代码,而无需重启应用程序。 另外,dnSpy提供了代码编辑功能,用户可以直接在反编译的代码上进行修改,并将这些更改保存回原始程序集。这种功能对于修正错误、优化代码或进行软件逆向工程研究都极为便利。 除了上述核心功能,dnSpy还拥有卓越的扩展性。它支持插件架构,允许开发者自定义并增加新的功能,如语法高亮显示、代码格式化工具等。这使得dnSpy能够根据用户的个性化需求进行定制,进一步提升了其灵活性和实用性。 在提供的压缩文件中,我们可以发现若干配置文件(例如dnSpy.exe.confi...
内容概要:本报告系统分析了2026—2031年中国生成式AI行业的发展现状、竞争格局与未来趋势。中国生成式AI市场已从“百模大战”进入“应用与算力双轮驱动”阶段,2025年核心市场规模约1,200亿元,用户规模达5.15亿,预计2031年将突破8,000亿元,复合增速约37%。产业链呈现“上游算力与数据、中游模型、下游应用”的结构,价值分布向高毛利率的AI芯片和垂类应用倾斜。DeepSeek、阿里通义等企业在开源、推理性能和生态构建方面引领创新,推动API成本大幅下降。竞争格局形成以字节、阿里、百度、腾讯、DeepSeek为首的第一梯队,市场集中度高,C端CR3达72%。未来趋势指向AI Agent规模化、多模态融合、视频生成爆发及“水电煤”式基础设施化。; 适合人群:关注人工智能产业发展的政府决策者、企业战略负责人、投资机构分析师、科技创业者及高校研究人员。; 使用场景及目标:①把握中国生成式AI市场整体规模、增长潜力与结构性机会;②理解产业链价值分配与核心技术演进方向;③识别头部企业竞争策略与商业模式优劣;④制定投资、创业或企业数字化转型决策提供数据支持与战略参考。; 阅读建议:本报告数据截至2026年6月,2026—2031年数据为预测测算值,使用者应结合动态政策、技术突破与市场竞争变化审慎研判,重点关注风险提示与分主体落地建议,以提升决策前瞻性与可行性。

4

社区成员

发帖
与我相关
我的任务
社区描述
openTK、OpenGL、WebGL技术学习交流
图形渲染c#程序人生 技术论坛(原bbs) 广东省·深圳市
社区管理员
  • 亿只小灿灿
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧