~luyu/comp5411-rendering-project

34fcff406efea9daee3e5363b62761a1b4ab021e — Luyu Cheng 2 months ago 6ecbea4
refactor: provide data in element arrays
1 files changed, 135 insertions(+), 10 deletions(-)

M src/lib.rs
M src/lib.rs => src/lib.rs +135 -10
@@ 50,7 50,10 @@ pub fn start() -> Result<(), JsValue> {
    context.use_program(Some(&program));

    // let vertices: [f32; 9] = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0];
    let (vertices, colors) = make_cube();
    // let cube = Cube::square(0.0);
    let cube = Model::cube();
    cube.debug();
    web_sys::console::log_1(&format!("Check: {:?}", cube.check()).into());

    let model_attribute_location = context
        .get_uniform_location(&program, "model")


@@ 75,7 78,7 @@ pub fn start() -> Result<(), JsValue> {
    // As a result, after `Float32Array::view` we have to be very careful not to
    // do any memory allocations before it's dropped.
    unsafe {
        let positions_array_buf_view = js_sys::Float32Array::view(&vertices);
        let positions_array_buf_view = js_sys::Float32Array::view(&cube.vertices);
        context.buffer_data_with_array_buffer_view(
            WebGl2RenderingContext::ARRAY_BUFFER,
            &positions_array_buf_view,


@@ 83,12 86,27 @@ pub fn start() -> Result<(), JsValue> {
        );
    }

    let index_buffer = context.create_buffer().ok_or("Failed to create buffer")?;
    context.bind_buffer(
        WebGl2RenderingContext::ELEMENT_ARRAY_BUFFER,
        Some(&index_buffer),
    );

    unsafe {
        let index_array_buf_view = js_sys::Uint16Array::view(&cube.indices);
        context.buffer_data_with_array_buffer_view(
            WebGl2RenderingContext::ELEMENT_ARRAY_BUFFER,
            &index_array_buf_view,
            WebGl2RenderingContext::STATIC_DRAW,
        );
    }

    let color_attribute_location = context.get_attrib_location(&program, "color");
    let color_buffer = context.create_buffer().ok_or("Failed to create buffer")?;
    context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&color_buffer));

    unsafe {
        let colors_array_buf_view = js_sys::Float32Array::view(&colors);
        let colors_array_buf_view = js_sys::Float32Array::view(&cube.colors);
        context.buffer_data_with_array_buffer_view(
            WebGl2RenderingContext::ARRAY_BUFFER,
            &colors_array_buf_view,


@@ 101,15 119,18 @@ pub fn start() -> Result<(), JsValue> {
        .ok_or("Could not create vertex array object")?;
    context.bind_vertex_array(Some(&vao));

    context.enable_vertex_attrib_array(position_attribute_location as u32);
    context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&position_buffer));
    context.vertex_attrib_pointer_with_i32(0, 3, WebGl2RenderingContext::FLOAT, false, 0, 0);
    context.enable_vertex_attrib_array(position_attribute_location as u32);

    context.bind_buffer(
        WebGl2RenderingContext::ELEMENT_ARRAY_BUFFER,
        Some(&index_buffer),
    );

    context.enable_vertex_attrib_array(color_attribute_location as u32);
    context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&color_buffer));
    context.vertex_attrib_pointer_with_i32(1, 3, WebGl2RenderingContext::FLOAT, false, 0, 0);
    context.enable_vertex_attrib_array(color_attribute_location as u32);

    // context.bind_vertex_array(Some(&vao));

    let pressed = Rc::new(Cell::new(false));
    let model = Rc::new(Cell::new(cgmath::Matrix4::identity()));


@@ 184,8 205,7 @@ pub fn start() -> Result<(), JsValue> {
                projection_slice,
            );

            let vert_count = (vertices.len() / 3) as i32;
            draw(&context, vert_count);
            draw(&context, cube.indices.len() as i32);
            request_animation_frame(f.borrow().as_ref().unwrap());
        }) as Box<FrameRequestCallback>));



@@ 195,9 215,108 @@ pub fn start() -> Result<(), JsValue> {
    Ok(())
}

struct Model {
    pub vertices: Vec<f32>,
    pub indices: Vec<u16>,
    pub colors: Vec<f32>,
}

impl Model {
    fn cube() -> Model {
        let mut vertices = Vec::with_capacity(3 * 8);
        let mut indices = Vec::with_capacity(6 * 6);
        let mut colors = Vec::with_capacity(3 * 8);
        // Generate 8 vertices of a cube.
        for i in 0..=0b111 { 
            let x = if i & 0b100 != 0 { 1.0 } else { -1.0 };
            let y = if i & 0b010 != 0 { 1.0 } else { -1.0 };
            let z = if i & 0b001 != 0 { 1.0 } else { -1.0 };
            vertices.extend_from_slice(&[x, y, z]);
            colors.extend_from_slice(&make_color());
        }
        // For each face,
        for i in 0..6 {
            let i0 = i / 2;
            let i1 = (i0 + 1) % 3;
            let i2 = (i0 + 2) % 3;
            let a = i & 1;
            for j in [0b00, 0b01, 0b10, 0b01, 0b10, 0b11] {
                let b = j & 0b01;
                let c = (j & 0b10) >> 1;
                indices.push((a << i0) | (b << i1) | (c << i2) as u16);
            }
        }
        Model {
            vertices,
            indices,
            colors,
        }
    }

    pub fn check(&self) -> bool {
        if self.vertices.len() != self.colors.len() {
            return false;
        }
        for index in &self.indices {
            let i = *index as usize;
            if i >= self.vertices.len() / 3 {
                return false;
            }
        }
        true
    }

    pub fn debug(&self) {
        web_sys::console::log_1(
            &format!(
                "Vertices: {}",
                self.vertices
                    .chunks(3)
                    .map(|xs| format!("({}, {}, {})", xs[0], xs[1], xs[2]))
                    .collect::<Vec<_>>()
                    .join(", ")
            )
            .into(),
        );
        web_sys::console::log_1(&format!("Indices: {:?}", self.indices).into());
        web_sys::console::log_1(
            &format!(
                "Colors: {}",
                self.colors
                    .chunks(3)
                    .map(|xs| format!("({}, {}, {})", xs[0], xs[1], xs[2]))
                    .collect::<Vec<_>>()
                    .join(", ")
            )
            .into(),
        );
    }

    fn two_squares() -> Model {
        let mut front = Model::square(1.0);
        let mut back = Model::square(-1.0);
        for idx in back.indices.iter_mut() {
            *idx += (front.vertices.len() / 3) as u16;
        }
        front.vertices.extend_from_slice(&back.vertices);
        front.indices.extend_from_slice(&back.indices);
        front.colors.extend_from_slice(&back.colors);
        front
    }

    fn square(z: f32) -> Model {
        Model {
            vertices: vec![1.0, 1.0, z, 1.0, -1.0, z, -1.0, 1.0, z, -1.0, -1.0, z],
            indices: vec![0, 1, 2, 1, 2, 3],
            colors: vec![1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0],
        }
    }
}

fn make_cube() -> (Vec<f32>, Vec<f32>) {
    let mut vertices = Vec::with_capacity(36);
    let mut colors = Vec::with_capacity(36);
    // For each face
    for i in 0..6 {
        let i0 = i / 2;
        let i1 = (i0 + 1) % 3;


@@ 234,7 353,13 @@ fn draw(context: &WebGl2RenderingContext, vert_count: i32) {
    context
        .clear(WebGl2RenderingContext::COLOR_BUFFER_BIT | WebGl2RenderingContext::DEPTH_BUFFER_BIT);

    context.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count);
    context.draw_elements_with_i32(
        WebGl2RenderingContext::TRIANGLES,
        vert_count,
        WebGl2RenderingContext::UNSIGNED_SHORT,
        0,
    );
    // context.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count);
}

pub fn compile_shader(