sebcrozet/kiss3d

UV mapping does not work (for me) [SOLVED]

Closed this issue · 2 comments

The UV mapping for meshes does not work for me. The following code should, as far as I can see, show a square with a checkered pattern in blue and yellow. Instead, I just get a yellow square.

The UV mapping feature is not documented in the kiss3d documentation, and there is no example in the code examples, so I may have made a mistake in my code; in this case, please advise the correct code.

Note that the code outputs the UV texture to uvmap.png.

By all means use this program (as corrected, if required) as an extra example in the crate.

extern crate image;
extern crate kiss3d;
extern crate nalgebra as na;

use crate::image::{GenericImage, Pixel};
use kiss3d::camera::{Camera, FirstPerson};
use kiss3d::light::Light;
use kiss3d::planar_camera::PlanarCamera;
use kiss3d::post_processing::PostProcessingEffect;
use kiss3d::resource::Texture;
use kiss3d::resource::{Mesh, TextureManager};

use kiss3d::window::{State, Window};
use na::Vector3;
use std::cell::RefCell;
use std::rc::Rc;

/** main program */
fn main() {
    let mut window = Window::new("kiss3d test");
    let mut state = AppState::new();
    state.generate_scene(&mut window);
    window.render_loop(state)
}
const UV_SIZE: u16 = 256;
/** state of the application */
struct AppState {
    camera: FirstPerson,
    frame_count: u32,
}
impl AppState {
    fn new() -> Self {
        let eye = na::Point3::new(2.0, 2.0, -10.0);
        let at = na::Point3::new(2.0, 2.0, 0.0);
        let mut camera = FirstPerson::new(eye.into(), at.into());
        camera.set_up_axis(Vector3::new(0.0, 1.0, 0.0));
        Self {
            frame_count: 0,
            camera,
        }
    }
    fn generate_scene(&mut self, window: &mut Window) {
        let mut group = window.add_group();
        let mesh = self.make_mesh();
        let mut c = group.add_mesh(Rc::new(RefCell::new(mesh)), Vector3::new(1.0, 1.0, 1.0));
        let texture = self.make_texture();
        c.set_texture(texture);
        c.enable_backface_culling(true);
        window.set_light(Light::StickToCamera);
    }
    fn make_mesh(&mut self) -> Mesh {
        let mut uvs: Vec<na::Point2<f32>> = vec![];
        let mut mesh_points: Vec<na::Point3<f32>> = vec![];
        let mut mesh_triangles: Vec<na::Point3<u16>> = vec![];
        for i in 0..5u16 {
            for j in 0..5u16 {
                let n = i * 5u16 + j;
                mesh_points.push(na::Point3::new(i as f32, j as f32, 0.0));
                uvs.push(na::Point2::new(
                    (i * UV_SIZE) as f32 / 4.0,
                    (j * UV_SIZE) as f32 / 4.0,
                ));
                if i != 4 && j != 4 {
                    mesh_triangles.push(na::Point3::new(n, n + 1, n + 6));
                    mesh_triangles.push(na::Point3::new(n, n + 6, n + 5));
                }
            }
        }
        Mesh::new(mesh_points, mesh_triangles, None, Some(uvs), false)
    }
    fn make_texture(&mut self) -> Rc<Texture> {
        let mut image = image::DynamicImage::new_rgb8(UV_SIZE as u32, UV_SIZE as u32);
        for x in 0..UV_SIZE {
            for y in 0..UV_SIZE {
                let pixel_colour = if (x / 32) % 2 == (y / 32) % 2 {
                    &[255, 255, 127, 255]
                } else {
                    &[0, 0, 127, 255]
                };
                image.put_pixel(x as u32, y as u32, *image::Rgba::from_slice(pixel_colour));
            }
        }
        image.save("uvmap.png").unwrap();
        let mut tm = TextureManager::new();
        tm.add_image(image, "groundmesh")
    }
}
impl State for AppState {
    /** `step` is called for each frame */
    fn step(&mut self, _window: &mut Window) {
        self.frame_count += 1;
    }
    /** return the camera and other data for the display */
    fn cameras_and_effect(
        &mut self,
    ) -> (
        Option<&mut dyn Camera>,
        Option<&mut dyn PlanarCamera>,
        Option<&mut dyn PostProcessingEffect>,
    ) {
        (Some(&mut self.camera), None, None)
    }
}
[package]
name = "kiss3d-window-test"
version = "0.1.0"
authors = ["martin <m.e@acm.org>"]
edition = "2018"

[dependencies]
ansi_term = "0.12.1"
image = "0.22.5"
kiss3d = "0.23.0"
nalgebra = "0.20.0"

I have tried using the github version of kiss3d, with the same issue.

kiss3d = { git = "https://github.com/sebcrozet/kiss3d" }
nalgebra = "0.21.0"

OK found the issue. The values in the UV map should have the range 0..1 but I assumed that the range was (0..n-1) where n was the dimension of my UV map (UV_SIZE in the above code i.e. 256).