render the model
This commit is contained in:
parent
184f9550d9
commit
db18de85ad
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -156,9 +156,9 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.24.0"
|
||||
version = "1.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
|
||||
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
|
|
@ -505,6 +505,9 @@ name = "glam"
|
|||
version = "0.30.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glow"
|
||||
|
|
@ -624,6 +627,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
|||
name = "hyperboloid"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"glam",
|
||||
"pollster",
|
||||
"wgpu",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ debug = false
|
|||
opt-level = 3
|
||||
|
||||
[dependencies]
|
||||
glam = { version = "0.30.9" }
|
||||
bytemuck = { version = "1.25.2", features = ["derive"] }
|
||||
glam = { version = "0.30.9", features = ["bytemuck"] }
|
||||
pollster = "0.4.0"
|
||||
wgpu = "27.0.1"
|
||||
winit = "0.30.12"
|
||||
|
|
|
|||
47
src/camera.rs
Normal file
47
src/camera.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
use glam::{Mat4, Vec3, vec3};
|
||||
|
||||
/// A camera always directed at the origin.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct OrbitalCamera {
|
||||
/// Horizontal position (angle), in radians from +X towards +Y.
|
||||
pub position_yaw: f32,
|
||||
|
||||
/// Vertical position (angle), in radians from XY plane towards +Z.
|
||||
pub position_pitch: f32,
|
||||
|
||||
/// Distance from the origin.
|
||||
pub distance: f32,
|
||||
}
|
||||
|
||||
impl OrbitalCamera {
|
||||
pub fn position(&self) -> Vec3 {
|
||||
let (y, x) = self.position_yaw.sin_cos();
|
||||
let (z, xy) = self.position_pitch.sin_cos();
|
||||
self.distance * vec3(xy * x, xy * y, z)
|
||||
}
|
||||
|
||||
pub fn direction(&self) -> Vec3 {
|
||||
let (y, x) = self.position_yaw.sin_cos();
|
||||
let (z, xy) = self.position_pitch.sin_cos();
|
||||
-vec3(xy * x, xy * y, z)
|
||||
}
|
||||
|
||||
pub fn transform(&self) -> Mat4 {
|
||||
// for yaw=0, pitch=0:
|
||||
// X -> -Z
|
||||
// Y -> -X
|
||||
// Z -> Y
|
||||
Mat4::from_translation(vec3(0., 0., self.distance))
|
||||
* Mat4::from_cols_array_2d(&[
|
||||
[0., 0., -1., 0.],
|
||||
[-1., 0., 0., 0.],
|
||||
[0., 1., 0., 0.],
|
||||
[0., 0., 0., 1.],
|
||||
]) * Mat4::from_euler(
|
||||
glam::EulerRot::ZYZ,
|
||||
0.,
|
||||
self.position_pitch,
|
||||
-self.position_yaw,
|
||||
)
|
||||
}
|
||||
}
|
||||
72
src/lib.rs
72
src/lib.rs
|
|
@ -1,22 +1,56 @@
|
|||
use std::error::Error;
|
||||
|
||||
use glam::{UVec2, Vec4, vec4};
|
||||
use glam::{Mat4, UVec2, Vec4, vec4};
|
||||
|
||||
mod camera;
|
||||
mod mesh;
|
||||
mod render;
|
||||
|
||||
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth16Unorm;
|
||||
const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct ShapeArgs {
|
||||
pub sides: u32,
|
||||
pub layers_up: u32,
|
||||
pub layers_down: u32,
|
||||
pub base_diameter: f32,
|
||||
pub height: f32,
|
||||
}
|
||||
|
||||
impl Default for ShapeArgs {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sides: 24,
|
||||
layers_up: 6,
|
||||
layers_down: 6,
|
||||
base_diameter: 36.0,
|
||||
height: 120.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct RedrawArgs {
|
||||
pub shape: ShapeArgs,
|
||||
pub background: Vec4,
|
||||
pub camera_yaw: f32,
|
||||
pub camera_pitch: f32,
|
||||
pub light_yaw: f32,
|
||||
pub light_pitch: f32,
|
||||
}
|
||||
|
||||
impl Default for RedrawArgs {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
shape: ShapeArgs::default(),
|
||||
background: vec4(0.05, 0.20, 0.85, 1.00),
|
||||
camera_yaw: std::f32::consts::FRAC_PI_2,
|
||||
camera_pitch: std::f32::consts::FRAC_PI_3,
|
||||
light_yaw: 0.,
|
||||
light_pitch: 2. * std::f32::consts::FRAC_PI_3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,6 +67,8 @@ pub struct Core {
|
|||
surface: wgpu::Surface<'static>,
|
||||
|
||||
depth: wgpu::Texture,
|
||||
|
||||
pipeline: render::Pipeline,
|
||||
}
|
||||
|
||||
impl Core {
|
||||
|
|
@ -48,21 +84,40 @@ impl Core {
|
|||
|
||||
Self::configure_surface(&surface, &device, pixel_size);
|
||||
|
||||
let pipeline = render::Pipeline::new(&device);
|
||||
|
||||
Self {
|
||||
device,
|
||||
queue,
|
||||
surface,
|
||||
depth,
|
||||
pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&self, output: &wgpu::Texture, args: &RedrawArgs) {
|
||||
let mesh = mesh::generate();
|
||||
let mesh = faceted_mesh(&mesh);
|
||||
let mesh = render::Mesh::new(&self.device, &mesh);
|
||||
|
||||
let aspect = {
|
||||
let size = output.size();
|
||||
let w = size.width as f32;
|
||||
let h = size.height as f32;
|
||||
w / h
|
||||
};
|
||||
let camera = camera::OrbitalCamera {
|
||||
position_yaw: args.camera_yaw,
|
||||
position_pitch: args.camera_pitch,
|
||||
distance: 5. * args.shape.base_diameter,
|
||||
};
|
||||
let perspective = Mat4::perspective_lh(std::f32::consts::FRAC_PI_3, aspect, 1e1, 1e3);
|
||||
self.pipeline.set_look(
|
||||
&self.queue,
|
||||
render::LookParams {
|
||||
m: perspective * camera.transform(),
|
||||
},
|
||||
);
|
||||
self.queue.submit([]); // flush buffer updates
|
||||
|
||||
let view = output.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
|
|
@ -98,6 +153,8 @@ impl Core {
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
self.pipeline.render(&mut pass, [&mesh]);
|
||||
|
||||
drop(pass);
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
}
|
||||
|
|
@ -177,3 +234,16 @@ pub async fn init_gpu_inner<E: Error + 'static>(
|
|||
surface,
|
||||
})
|
||||
}
|
||||
|
||||
fn faceted_mesh(mesh: &mesh::Mesh) -> Vec<render::Vertex> {
|
||||
let mut ret = Vec::new();
|
||||
for face in &mesh.faces {
|
||||
let face = face.map(|index| mesh.vertices[index]);
|
||||
let u = face[1] - face[0];
|
||||
let v = face[2] - face[0];
|
||||
let normal = u.cross(v).normalize();
|
||||
let face = face.map(|position| render::Vertex { position, normal });
|
||||
ret.extend(face);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
|
|
|||
27
src/mesh.wgsl
Normal file
27
src/mesh.wgsl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
struct LookParams {
|
||||
m: mat4x4f,
|
||||
}
|
||||
|
||||
struct Vertex {
|
||||
@location(0) position: vec3f,
|
||||
@location(1) normal: vec3f,
|
||||
}
|
||||
|
||||
struct Varying {
|
||||
@builtin(position) screen: vec4f,
|
||||
@location(0) normal: vec3f,
|
||||
}
|
||||
|
||||
@group(0) @binding(0) var<uniform> look: LookParams;
|
||||
|
||||
@vertex
|
||||
fn on_vertex(in: Vertex) -> Varying {
|
||||
let pos = look.m * vec4f(in.position, 1.0);
|
||||
let normal = in.normal;
|
||||
return Varying(pos, normal);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn on_fragment(in: Varying) -> @location(0) vec4f {
|
||||
return vec4f(0.5 + 0.5 * in.normal, 1.0);
|
||||
}
|
||||
148
src/render.rs
Normal file
148
src/render.rs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
use std::mem::offset_of;
|
||||
|
||||
use bytemuck::{Pod, Zeroable, bytes_of, cast_slice};
|
||||
use glam::{Mat4, Vec3};
|
||||
use wgpu::util::DeviceExt as _;
|
||||
|
||||
use crate::{DEPTH_FORMAT, OUTPUT_FORMAT};
|
||||
|
||||
static MESH_SHADER: &str = include_str!("mesh.wgsl");
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct LookParams {
|
||||
pub m: Mat4,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
pub position: Vec3,
|
||||
pub normal: Vec3,
|
||||
}
|
||||
|
||||
pub struct Mesh {
|
||||
vertex_buffer: wgpu::Buffer,
|
||||
vertex_count: u32,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
pub fn new(device: &wgpu::Device, vertices: &[Vertex]) -> Self {
|
||||
let vertex_count = vertices.len().try_into().expect("too many vertices");
|
||||
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
contents: cast_slice(vertices),
|
||||
});
|
||||
Self {
|
||||
vertex_buffer,
|
||||
vertex_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pipeline {
|
||||
look_buf: wgpu::Buffer,
|
||||
bindings: wgpu::BindGroup,
|
||||
pipeline: wgpu::RenderPipeline,
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
let look_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
size: size_of::<LookParams>() as u64,
|
||||
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
source: wgpu::ShaderSource::Wgsl(MESH_SHADER.into()),
|
||||
});
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
layout: None,
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: None,
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
buffers: &[wgpu::VertexBufferLayout {
|
||||
array_stride: size_of::<Vertex>() as u64,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
shader_location: 0,
|
||||
offset: offset_of!(Vertex, position) as u64,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
},
|
||||
wgpu::VertexAttribute {
|
||||
shader_location: 1,
|
||||
offset: offset_of!(Vertex, normal) as u64,
|
||||
format: wgpu::VertexFormat::Float32x3,
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
// cull_mode: Some(wgpu::Face::Front),
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: DEPTH_FORMAT,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: None,
|
||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: OUTPUT_FORMAT,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
multiview: None,
|
||||
cache: None,
|
||||
});
|
||||
let bindings = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
layout: &pipeline.get_bind_group_layout(0),
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: look_buf.as_entire_binding(),
|
||||
}],
|
||||
});
|
||||
Self {
|
||||
look_buf,
|
||||
bindings,
|
||||
pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_look(&self, queue: &wgpu::Queue, look: LookParams) {
|
||||
queue.write_buffer(&self.look_buf, 0, bytes_of(&look));
|
||||
}
|
||||
|
||||
pub fn render<'a>(
|
||||
&self,
|
||||
pass: &mut wgpu::RenderPass,
|
||||
meshes: impl IntoIterator<Item = &'a Mesh>,
|
||||
) {
|
||||
pass.set_pipeline(&self.pipeline);
|
||||
pass.set_bind_group(0, &self.bindings, &[]);
|
||||
for mesh in meshes {
|
||||
pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
|
||||
pass.draw(0..mesh.vertex_count, 0..1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,11 +11,25 @@ struct alignas(16) Vec4 {
|
|||
namespace ffi {
|
||||
struct Core;
|
||||
|
||||
struct ShapeArgs {
|
||||
std::uint32_t sides;
|
||||
std::uint32_t layers_up;
|
||||
std::uint32_t layers_down;
|
||||
float base_diameter;
|
||||
float height;
|
||||
};
|
||||
|
||||
struct RedrawArgs {
|
||||
ShapeArgs shape;
|
||||
Vec4 background;
|
||||
float camera_yaw;
|
||||
float camera_pitch;
|
||||
float light_yaw;
|
||||
float light_pitch;
|
||||
};
|
||||
} // namespace ffi
|
||||
|
||||
using ffi::ShapeArgs;
|
||||
using ffi::RedrawArgs;
|
||||
|
||||
class MutCore {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,20 @@ Hyperboloid::~Hyperboloid() = default;
|
|||
|
||||
void Hyperboloid::updateView() {
|
||||
const auto color = m_ui->inBackground->color();
|
||||
RedrawArgs args{
|
||||
const ShapeArgs shape {
|
||||
.sides = (std::uint32_t)m_ui->sides->value(),
|
||||
.layers_up = (std::uint32_t)m_ui->layersUp->value(),
|
||||
.layers_down = (std::uint32_t)m_ui->layersDown->value(),
|
||||
.base_diameter = (float)m_ui->dia->value(),
|
||||
.height = (float)m_ui->height->value(),
|
||||
};
|
||||
const RedrawArgs args{
|
||||
.shape = shape,
|
||||
.background = { color.redF(), color.greenF(), color.blueF(), 1.00 },
|
||||
.camera_yaw = qDegreesToRadians((float)m_ui->camYaw->value()),
|
||||
.camera_pitch = qDegreesToRadians((float)m_ui->camPitch->value()),
|
||||
.light_yaw = 0.0,
|
||||
.light_pitch = qDegreesToRadians((float)m_ui->lightPitch->value()),
|
||||
};
|
||||
m_ui->viewport->setView(args);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,21 +41,241 @@
|
|||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Background color</string>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Camera</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Yaw</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="camYaw">
|
||||
<property name="minimum">
|
||||
<number>-180</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>45</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="camPitch">
|
||||
<property name="minimum">
|
||||
<number>-90</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>90</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KColorCombo" name="inBackground">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>25</red>
|
||||
<green>220</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Light</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Pitch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="lightPitch">
|
||||
<property name="minimum">
|
||||
<number>-90</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>90</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Shape</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Sides</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sides">
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Layers up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="layersUp">
|
||||
<property name="maximum">
|
||||
<number>11</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Layers down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="layersDown">
|
||||
<property name="maximum">
|
||||
<number>11</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Base diameter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="dia">
|
||||
<property name="suffix">
|
||||
<string> mm</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="stepType">
|
||||
<enum>QAbstractSpinBox::AdaptiveDecimalStepType</enum>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>36.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="height">
|
||||
<property name="suffix">
|
||||
<string> mm</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>500.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>120.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Appearance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Background color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KColorCombo" name="inBackground">
|
||||
<property name="color">
|
||||
<color>
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -97,8 +317,8 @@
|
|||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1531</x>
|
||||
<y>115</y>
|
||||
<x>1585</x>
|
||||
<y>803</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>799</x>
|
||||
|
|
@ -106,6 +326,134 @@
|
|||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>camYaw</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1520</x>
|
||||
<y>142</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1449</x>
|
||||
<y>133</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>camPitch</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1550</x>
|
||||
<y>192</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1447</x>
|
||||
<y>198</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>lightPitch</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1565</x>
|
||||
<y>286</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1445</x>
|
||||
<y>265</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>sides</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1521</x>
|
||||
<y>370</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1448</x>
|
||||
<y>378</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>layersUp</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1490</x>
|
||||
<y>436</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1446</x>
|
||||
<y>441</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>layersDown</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1478</x>
|
||||
<y>513</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1446</x>
|
||||
<y>515</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>dia</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1472</x>
|
||||
<y>611</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1446</x>
|
||||
<y>629</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>height</sender>
|
||||
<signal>valueChanged(double)</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>updateView()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>1476</x>
|
||||
<y>686</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>1446</x>
|
||||
<y>686</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>updateView()</slot>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user