Help! "Cannot index into a value of type 'f32' "

I rewrite my spining-cube program in C and I consider that how to make this error compiling. Can someone to show my wheres my problem is.

Error[E0608]: cannot index into a value of type 'f32'
--> src/main.rs:53:19
                  if (ooz > ZBUFFER[idx]) {

Rust

#[warn(unused_imports)]

const CUBEWIDTH: f32 = 10.0;
const WIDTH: f32 = 160.0;
const HEIGHT: f32 = 40.0;
const K1: f32 = 40.0;
const ZBUFFER: f32 = 160.0 * 44.0;
const BUFFER: f32 = 160.0 * 44.0;
const BACKGROUNDASCIICODE: char = ' ';
const DISTANCEFROMCAM: f32 = 100.0;
const HORIZONTALOFFSET: f32 = 0.0;

const A: f32 = 0.0;
const B: f32 = 0.0;
const C: f32 = 0.0;

pub fn calculate_x(i: f32, j: f32, k: f32) -> f32 { 
    return j * A.sin() * B.sin() * C.cos() - k * A.cos() * B.sin() * C.cos() +
    j * A.cos() * C.sin() + k * A.sin() * C.sin() + i * B.cos() * C.cos();
}

pub fn calculate_y(i: f32, j: f32, k: f32) -> f32 {
    return j * A.cos() * C.cos() + k * A.sin() * C.cos() - j * A.sin() * B.sin() * C.sin() +
    k * A.cos() * B.sin() * C.sin() - i * B.cos() * C.sin();
}

pub fn calculate_z(i: f32, j: f32, k: f32) -> f32 {
    return k * A.cos() * B.cos() - j * A.sin() * B.cos() + i * B.sin();
}

pub fn calculate_for_surface(cube_x: f32,  cube_y: f32, cube_z: f32, ch: i32) {
    let mut _x: f32 = 0.0;
    let mut _y: f32 = 0.0;
    let mut _z: f32 = 0.0;

    _x = calculate_x(cube_x, cube_y, cube_z);
    _y = calculate_y(cube_x, cube_y, cube_z);
    _z = calculate_z(cube_x, cube_y, cube_z) + DISTANCEFROMCAM;

    let mut ooz: f32 = 0.0;

    ooz = 1.0 / _z;

    let mut xp: f32 = 0.0;
    let mut yp: f32 = 0.0;
    let mut idx: f32 = 0.0; 

    xp = WIDTH / 2.0 + HORIZONTALOFFSET + K1 * ooz * _x * 2.0;
    yp = HEIGHT / 2.0 + K1 * ooz * _y;

    idx = xp + yp * WIDTH;
    if (idx >= 0.0 && idx < WIDTH * HEIGHT) {
        if (ooz > ZBUFFER[idx]) {
            ZBUFFER[idx] = ooz;
            BUFFER[idx] = ch;
        }
    } 
}

fn main() {
    println!("Hello World!");
}

My program in C

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

float A, B, C;

float cubeWidth = 10;
int width = 160, height = 44;
float zBuffer[160 * 44];
char buffer[160 * 44];
int backgroundASCIICode = ' ';
int distanceFromCam = 100;
float horizontalOffset;
float K1 = 40;

float incrementSpeed = 0.6;

float x, y, z;
float ooz;
int xp, yp;
int idx;

float calculateX(int i, int j, int k) {
    return j * sin(A) * sin(B) * cos(C) - k * cos(A) * sin(B) * cos(C) +
    j * cos(A) * sin(C) + k * sin(A) * sin(C) + i * cos(B) * cos(C);
}

float calculateY(int i, int j, int k) {
    return j * cos(A) * cos(C) + k * sin(A) * cos(C) - j * sin(A) * sin(B) * sin(C) +
    k * cos(A) * sin(B) * sin(C) - i * cos(B) * sin(C);
}

float calculateZ(int i, int j, int k) {
    return k * cos(A) * cos(B) - j * sin(A) * cos(B) + i * sin(B);
}

void calculateForSurface(float cubeX, float cubeY, float cubeZ, int ch) {
    x = calculateX(cubeX, cubeY, cubeZ);
    y = calculateY(cubeX, cubeY, cubeZ);
    z = calculateZ(cubeX, cubeY, cubeZ) + distanceFromCam;

    ooz = 1 / z;

    xp = (int)(width / 2 + horizontalOffset + K1 * ooz * x * 2);
    yp = (int)(height / 2 + K1 * ooz * y);

    idx =  xp + yp * width;
    if (idx >= 0 && idx < width * height) {
        if (ooz > zBuffer[idx]) {
            zBuffer[idx] = ooz;
            buffer[idx] = ch;
        }
    }
}

int main() {
    printf("\x1b[2J");
    while(1) {
        memset(buffer, backgroundASCIICode, width * height);
        memset(zBuffer, 0, width * height * 4);
        cubeWidth = 20;
        horizontalOffset = -2 * cubeWidth;
        // first cube
        for(float cubeX = -cubeWidth; cubeX < cubeWidth; cubeX += incrementSpeed) {
            for(float cubeY = -cubeWidth; cubeY < cubeWidth; cubeY += incrementSpeed) {
                calculateForSurface(cubeX, cubeY, -cubeWidth, '@');
                calculateForSurface(cubeWidth, cubeY, cubeX, '$');
                calculateForSurface(-cubeWidth, cubeY, -cubeX, '~');
                calculateForSurface(-cubeX, cubeY, cubeWidth, '#');
                calculateForSurface(cubeX, -cubeWidth, -cubeY, ';');
                calculateForSurface(cubeX, cubeWidth, cubeY, '+');
            }
        }
        printf("\x1b[H");
        for (int k = 0; k < width * height; k++) {
            putchar(k % width ? buffer[k] : 10);
        }
        A += 0.05;
        B += 0.05;
        C += 0.01;
        usleep(8000 * 2);
    }   
    return 0;
}

Remove this...

Change this...

...to this...
let idx = (xp + yp * WIDTH) as usize;

You are literally saying that your ZBUFFER constant is the number 160 * 44. It's not an array (it looks like it should be an array based on its name and the C code).

1 Like

I would advise to leave only this

This code does the same. And it looks like you have more than one problem.

Besides addressing the confusion of single numbers with arrays in C that @H2CO3 pointed out, you will need to identify which one of the global variables in your C code are constant, and thus can be const in Rust, and which ones are mutated, and thus need to be mutable variables. The mutable ones should best not be global variables, as Rust does (rightfully) not encourage usage of global mutable variables, and doing so anyways would be unnecessarily tedious (involving Mutex or perhaps thread-locals with Cell; or maybe even unsafe code). You can e.g. use local variables in main, and pass mutable references to functions if functions need to access these variables.

On that note, even the C code seems a bit weird. Why is cubeWidth initially 10, but set to 20 before ever being used (and repeatedly, in every iteration)?

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.