Last active
August 7, 2024 09:08
-
-
Save mcneds/799788f3a9d4395f964f82b869511dc5 to your computer and use it in GitHub Desktop.
Parkour simulation 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import matplotlib.pyplot as plt | |
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg | |
import tkinter as tk | |
from tkinter import ttk | |
# Define the parameters for the paraboloid | |
vertex_x = 0 | |
vertex_y = 1 | |
root1 = -4.25 | |
root2 = root1 * -1 | |
step = 1 / 16 | |
# Create a grid of x and y values | |
x = np.arange(root1, root2 + step, step) | |
y = np.arange(root1, root2 + step, step) | |
X, Y = np.meshgrid(x, y) | |
# Calculate the z values for the original paraboloid | |
a = -1 / ((root2 - vertex_x) ** 2) | |
Z = a * (X ** 2 + Y ** 2) + vertex_y | |
# Function to create the paraboloid based on combined root scaling | |
def create_paraboloid(difficulty): | |
if difficulty <= 5: | |
# Logarithmic scaling for root from 0 to 3 | |
log_scale = (difficulty / 5) | |
new_root = 3 * log_scale | |
else: | |
# Exponential scaling for root from 3 to 4.25 | |
exp_scale = (difficulty - 5) / 5 | |
new_root = 3 + exp_scale * (root2 - 3) | |
a_difficulty = -1 / (new_root ** 2) | |
Z_difficulty = a_difficulty * (X ** 2 + Y ** 2) + vertex_y | |
return Z_difficulty, new_root | |
# Precompute base paraboloid once | |
base_Z_difficulty, _ = create_paraboloid(1) | |
# Calculate the outer bounds for the true simulation | |
def calculate_outer_bounds_paraboloid(difficulty): | |
Z_difficulty, _ = create_paraboloid(difficulty) | |
max_Z_difficulty = np.max(Z_difficulty) | |
min_Z_difficulty = np.min(Z_difficulty) | |
# Extend the grid to cover the 20x20 grid space | |
outer_X = np.arange(root1 - 10 * step, root2 + 10 * step + step, step) | |
outer_Y = np.arange(root1 - 10 * step, root2 + 10 * step + step, step) | |
outer_X, outer_Y = np.meshgrid(outer_X, outer_Y) | |
a_difficulty = -1 / (4.25 ** 2) | |
outer_Z_difficulty = a_difficulty * (outer_X ** 2 + outer_Y ** 2) + vertex_y | |
return outer_X, outer_Y, outer_Z_difficulty, min_Z_difficulty, max_Z_difficulty | |
# Function to update the plot | |
def update_plot(difficulty): | |
global base_Z_difficulty | |
Z_difficulty, root_distance = create_paraboloid(difficulty) | |
if difficulty != 1: | |
base_Z_difficulty = Z_difficulty | |
ax.clear() | |
if show_original.get(): | |
ax.scatter(X, Y, Z, color='blue', s=1) | |
if show_difficulty.get(): | |
if show_true_simulation.get(): | |
outer_X, outer_Y, outer_Z_difficulty, _, _ = calculate_outer_bounds_paraboloid(difficulty) | |
ax.scatter(outer_X, outer_Y, outer_Z_difficulty, color='green', s=1) | |
else: | |
ax.scatter(X, Y, Z_difficulty, color='green', s=1) | |
if show_ground_plane.get(): | |
ax.plot_surface(X, Y, np.zeros_like(X), color='gray', alpha=0.5) | |
ax.scatter(0, 0, 0, color='red', s=50, label='Jump Origin', zorder=1000000) # Ensure the origin point is plotted last | |
ax.set_title(f'Paraboloid with Difficulty {difficulty}') | |
ax.set_xlabel('X') | |
ax.set_ylabel('Y') | |
ax.set_zlabel('Z') | |
root_label.config(text=f"Root Distance: {root_distance:.4f}") | |
canvas.draw() | |
# Function to handle slider interaction | |
def on_slider_change(event): | |
slider_paused.set(False) | |
update_plot(slider.get()) | |
slider_paused.set(True) | |
# Function to pause rendering during slider interaction | |
def on_slider_scrub(event): | |
slider_paused.set(False) | |
# Creating the Tkinter window | |
root = tk.Tk() | |
root.title("Paraboloid Visualization") | |
# Create a figure and axis for the 3D plot | |
fig = plt.figure(figsize=(8, 6)) | |
ax = fig.add_subplot(111, projection='3d') | |
# Embed the plot in the Tkinter window | |
canvas = FigureCanvasTkAgg(fig, master=root) | |
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) | |
# Create Boolean variables for toggling visibility | |
show_original = tk.BooleanVar(value=True) | |
show_difficulty = tk.BooleanVar(value=True) | |
show_ground_plane = tk.BooleanVar(value=True) | |
show_true_simulation = tk.BooleanVar(value=False) | |
slider_paused = tk.BooleanVar(value=True) | |
# Create toggle buttons | |
toggle_original_btn = ttk.Checkbutton(root, text="Toggle Original Paraboloid", variable=show_original, command=lambda: update_plot(slider.get())) | |
toggle_original_btn.pack(side=tk.LEFT, padx=10, pady=10) | |
toggle_difficulty_btn = ttk.Checkbutton(root, text="Toggle Difficulty Paraboloid", variable=show_difficulty, command=lambda: update_plot(slider.get())) | |
toggle_difficulty_btn.pack(side=tk.LEFT, padx=10, pady=10) | |
toggle_ground_plane_btn = ttk.Checkbutton(root, text="Toggle Ground Plane", variable=show_ground_plane, command=lambda: update_plot(slider.get())) | |
toggle_ground_plane_btn.pack(side=tk.LEFT, padx=10, pady=10) | |
toggle_true_simulation_btn = ttk.Checkbutton(root, text="Toggle True Simulation", variable=show_true_simulation, command=lambda: update_plot(slider.get())) | |
toggle_true_simulation_btn.pack(side=tk.LEFT, padx=10, pady=10) | |
# Create a slider for adjusting the difficulty | |
slider = ttk.Scale(root, from_=1, to=10, orient=tk.HORIZONTAL) | |
slider.set(1) | |
slider.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=10) | |
slider.bind("<ButtonRelease-1>", on_slider_change) | |
slider.bind("<ButtonPress-1>", on_slider_scrub) | |
# Display for root distance | |
root_label = tk.Label(root, text="Root Distance: 0.0000") | |
root_label.pack(side=tk.BOTTOM, padx=10, pady=10) | |
# Create the initial plot | |
update_plot(1) | |
# Run the Tkinter event loop | |
root.mainloop() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <omp.h> | |
#include <hdf5.h> | |
#define ROOT1 -68 | |
#define ROOT2 68 | |
#define VERTEX_Y 16 | |
#define STEP 1 | |
#define MAX_HEIGHT 160 // 10 blocks, each block is 16 pixels | |
#define CHUNK_SIZE 50 | |
// Function prototypes | |
double* create_max_paraboloid(); | |
double calculate_difficulty(double root_distance); | |
void generate_points(double** points, int* point_count); | |
void save_chunk_to_file(double* chunk_data, int chunk_index, int point_count); | |
void combine_chunks(int total_chunks); | |
int main() { | |
int total_simulations = 400; // 20x20 origins | |
int completed_simulations = 0; | |
int chunk_index = 0; | |
int chunk_count = 0; | |
omp_set_num_threads(4); | |
printf("Starting full simulation\n"); | |
double* chunk_data = (double*)malloc(CHUNK_SIZE * 1000000 * 8 * sizeof(double)); // Allocate enough space for each chunk | |
if (chunk_data == NULL) { | |
fprintf(stderr, "Memory allocation failed for chunk data array\n"); | |
return 1; | |
} | |
int chunk_data_count = 0; | |
// Generate the maximum difficulty paraboloid points | |
double* max_paraboloid_points = NULL; | |
int max_paraboloid_point_count = 0; | |
generate_points(&max_paraboloid_points, &max_paraboloid_point_count); | |
// Offset these points according to different origins | |
for (int ox = -10; ox <= 10; ox++) { // 20px range centered on 0 | |
for (int oy = -10; oy <= 10; oy++) { // 20px range centered on 0 | |
for (int i = 0; i < max_paraboloid_point_count; i += 8) { | |
double abs_rx = max_paraboloid_points[i + 3] + ox; | |
double abs_ry = max_paraboloid_points[i + 4] + oy; | |
double abs_rz = max_paraboloid_points[i + 5]; | |
// Exclude points within the 20x20x32 exclusion zone below the origin | |
if (!(abs_rx >= -10 && abs_rx <= 10 && abs_ry >= -10 && abs_ry <= 10 && abs_rz >= -32 && abs_rz <= 0)) { | |
if (chunk_data_count >= CHUNK_SIZE * 1000000 * 8) { | |
save_chunk_to_file(chunk_data, chunk_index++, chunk_data_count); | |
chunk_data_count = 0; | |
} | |
chunk_data[chunk_data_count++] = ox; | |
chunk_data[chunk_data_count++] = oy; | |
chunk_data[chunk_data_count++] = 0; // Fixed origin z = 0 | |
chunk_data[chunk_data_count++] = abs_rx; | |
chunk_data[chunk_data_count++] = abs_ry; | |
chunk_data[chunk_data_count++] = abs_rz; | |
chunk_data[chunk_data_count++] = max_paraboloid_points[i + 6]; | |
chunk_data[chunk_data_count++] = max_paraboloid_points[i + 7]; | |
} | |
} | |
completed_simulations++; | |
printf("Simulation %d / %d completed.\n", completed_simulations, total_simulations); | |
} | |
} | |
// Save any remaining data | |
if (chunk_data_count > 0) { | |
save_chunk_to_file(chunk_data, chunk_index++, chunk_data_count); | |
} | |
free(max_paraboloid_points); | |
free(chunk_data); | |
printf("Data generation complete.\n"); | |
combine_chunks(chunk_index); | |
printf("All chunks combined into final file.\n"); | |
return 0; | |
} | |
double* create_max_paraboloid() { | |
static double Z_difficulty[(ROOT2 - ROOT1 + 1) * (ROOT2 - ROOT1 + 1)]; | |
int index = 0; | |
double a_difficulty = -1.0 / ((68.0 / 16.0) * (68.0 / 16.0)); // Max root distance for max difficulty | |
for (int x = ROOT1; x <= ROOT2; x += STEP) { | |
for (int y = ROOT1; y <= ROOT2; y += STEP) { | |
double z = a_difficulty * (x * x + y * y) + VERTEX_Y; | |
Z_difficulty[index++] = z; // Allow negative z values | |
} | |
} | |
return Z_difficulty; | |
} | |
double calculate_difficulty(double root_distance) { | |
double root_blocks = root_distance / 16.0; | |
if (root_blocks <= 3) { | |
return (root_blocks / 3.0) * 5.0; | |
} else { | |
return 5.0 + ((root_blocks - 3.0) / (4.25 - 3.0)) * 5.0; | |
} | |
} | |
void generate_points(double** points, int* point_count) { | |
int max_points = 1000000; // Large initial allocation size | |
*points = (double*)malloc(max_points * 8 * sizeof(double)); | |
if (*points == NULL) { | |
fprintf(stderr, "Memory allocation failed for points array\n"); | |
exit(1); | |
} | |
*point_count = 0; | |
double* Z_difficulty = create_max_paraboloid(); | |
int index = 0; | |
for (int x = ROOT1; x <= ROOT2; x += STEP) { | |
for (int y = ROOT1; y <= ROOT2; y += STEP) { | |
double rz = Z_difficulty[index++]; | |
int abs_rx = x; | |
int abs_ry = y; | |
int abs_rz = rz; | |
double root_distance = sqrt(abs_rx * abs_rx + abs_ry * abs_ry); | |
double difficulty = calculate_difficulty(root_distance); | |
if (*point_count >= max_points * 8) { | |
max_points *= 2; | |
*points = (double*)realloc(*points, max_points * 8 * sizeof(double)); | |
if (*points == NULL) { | |
fprintf(stderr, "Memory reallocation failed for points array\n"); | |
exit(1); | |
} | |
} | |
(*points)[(*point_count)++] = 0; | |
(*points)[(*point_count)++] = 0; | |
(*points)[(*point_count)++] = 0; // Fixed origin z = 0 | |
(*points)[(*point_count)++] = abs_rx; | |
(*points)[(*point_count)++] = abs_ry; | |
(*points)[(*point_count)++] = abs_rz; | |
(*points)[(*point_count)++] = root_distance; | |
(*points)[(*point_count)++] = difficulty; | |
} | |
} | |
} | |
void save_chunk_to_file(double* chunk_data, int chunk_index, int point_count) { | |
char filename[50]; | |
sprintf(filename, "simulation_chunk_%d.h5", chunk_index); | |
printf("Saving chunk %d to %s\n", chunk_index, filename); | |
hid_t file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); | |
if (file_id < 0) { | |
fprintf(stderr, "Error: Failed to create file %s\n", filename); | |
return; | |
} | |
hsize_t dims[2] = { point_count / 8, 8 }; | |
hid_t dataspace_id = H5Screate_simple(2, dims, NULL); | |
if (dataspace_id < 0) { | |
fprintf(stderr, "Error: Failed to create dataspace\n"); | |
H5Fclose(file_id); | |
return; | |
} | |
hid_t plist_id = H5Pcreate(H5P_DATASET_CREATE); | |
H5Pset_deflate(plist_id, 9); // Maximum compression level | |
H5Pset_chunk(plist_id, 2, dims); | |
hid_t dataset_id = H5Dcreate2(file_id, "data", H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT, plist_id, H5P_DEFAULT); | |
if (dataset_id < 0) { | |
fprintf(stderr, "Error: Failed to create dataset\n"); | |
H5Sclose(dataspace_id); | |
H5Pclose(plist_id); | |
H5Fclose(file_id); | |
return; | |
} | |
if (H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, chunk_data) < 0) { | |
fprintf(stderr, "Error: Failed to write data to dataset\n"); | |
} else { | |
printf("Data successfully written to %s\n", filename); | |
} | |
H5Dclose(dataset_id); | |
H5Sclose(dataspace_id); | |
H5Pclose(plist_id); | |
H5Fclose(file_id); | |
printf("Chunk %d saved to %s\n", chunk_index, filename); | |
} | |
void combine_chunks(int total_chunks) { | |
printf("Combining %d chunks into final file\n", total_chunks); | |
hid_t final_file_id = H5Fcreate("simulation_data.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); | |
if (final_file_id < 0) { | |
fprintf(stderr, "Error: Failed to create final file simulation_data.h5\n"); | |
return; | |
} | |
hsize_t total_size = 0; | |
for (int i = 0; i < total_chunks; i++) { | |
char filename[50]; | |
sprintf(filename, "simulation_chunk_%d.h5", i); | |
hid_t chunk_file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); | |
if (chunk_file_id < 0) { | |
fprintf(stderr, "Error: Failed to open chunk file %s\n", filename); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hid_t dataset_id = H5Dopen2(chunk_file_id, "data", H5P_DEFAULT); | |
if (dataset_id < 0) { | |
fprintf(stderr, "Error: Failed to open dataset in chunk file %s\n", filename); | |
H5Fclose(chunk_file_id); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hid_t dataspace_id = H5Dget_space(dataset_id); | |
hsize_t dims[2]; | |
H5Sget_simple_extent_dims(dataspace_id, dims, NULL); | |
total_size += dims[0] * dims[1]; | |
H5Sclose(dataspace_id); | |
H5Dclose(dataset_id); | |
H5Fclose(chunk_file_id); | |
} | |
hsize_t final_dims[2] = { total_size / 8, 8 }; | |
hid_t final_dataspace_id = H5Screate_simple(2, final_dims, NULL); | |
if (final_dataspace_id < 0) { | |
fprintf(stderr, "Error: Failed to create dataspace for final file\n"); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hid_t final_plist_id = H5Pcreate(H5P_DATASET_CREATE); | |
H5Pset_deflate(final_plist_id, 9); // Maximum compression level | |
H5Pset_chunk(final_plist_id, 2, final_dims); | |
hid_t final_dataset_id = H5Dcreate2(final_file_id, "data", H5T_NATIVE_DOUBLE, final_dataspace_id, H5P_DEFAULT, final_plist_id, H5P_DEFAULT); | |
if (final_dataset_id < 0) { | |
fprintf(stderr, "Error: Failed to create dataset in final file\n"); | |
H5Sclose(final_dataspace_id); | |
H5Pclose(final_plist_id); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hsize_t offset = 0; | |
for (int i = 0; i < total_chunks; i++) { | |
char filename[50]; | |
sprintf(filename, "simulation_chunk_%d.h5", i); | |
hid_t chunk_file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); | |
if (chunk_file_id < 0) { | |
fprintf(stderr, "Error: Failed to open chunk file %s\n", filename); | |
H5Fclose(final_dataset_id); | |
H5Fclose(final_dataspace_id); | |
H5Pclose(final_plist_id); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hid_t dataset_id = H5Dopen2(chunk_file_id, "data", H5P_DEFAULT); | |
if (dataset_id < 0) { | |
fprintf(stderr, "Error: Failed to open dataset in chunk file %s\n", filename); | |
H5Fclose(chunk_file_id); | |
H5Fclose(final_dataset_id); | |
H5Fclose(final_dataspace_id); | |
H5Pclose(final_plist_id); | |
H5Fclose(final_file_id); | |
return; | |
} | |
hid_t dataspace_id = H5Dget_space(dataset_id); | |
hsize_t dims[2]; | |
H5Sget_simple_extent_dims(dataspace_id, dims, NULL); | |
hsize_t chunk_size = dims[0] * dims[1]; | |
double* chunk_data = (double*)malloc(chunk_size * sizeof(double)); | |
if (chunk_data == NULL) { | |
fprintf(stderr, "Error: Memory allocation failed for chunk data\n"); | |
H5Sclose(dataspace_id); | |
H5Dclose(dataset_id); | |
H5Fclose(chunk_file_id); | |
H5Fclose(final_dataset_id); | |
H5Fclose(final_dataspace_id); | |
H5Pclose(final_plist_id); | |
H5Fclose(final_file_id); | |
return; | |
} | |
H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, chunk_data); | |
hsize_t final_offset[2] = { offset, 0 }; | |
hsize_t final_count[2] = { dims[0], dims[1] }; | |
hid_t final_memspace_id = H5Screate_simple(2, final_count, NULL); | |
H5Sselect_hyperslab(final_dataspace_id, H5S_SELECT_SET, final_offset, NULL, final_count, NULL); | |
H5Dwrite(final_dataset_id, H5T_NATIVE_DOUBLE, final_memspace_id, final_dataspace_id, H5P_DEFAULT, chunk_data); | |
free(chunk_data); | |
H5Sclose(final_memspace_id); | |
H5Sclose(dataspace_id); | |
H5Dclose(dataset_id); | |
H5Fclose(chunk_file_id); | |
offset += dims[0]; | |
// Delete the chunk file after combining | |
if (remove(filename) != 0) { | |
fprintf(stderr, "Error: Failed to delete chunk file %s\n", filename); | |
} else { | |
printf("Chunk file %s deleted successfully\n", filename); | |
} | |
} | |
H5Dclose(final_dataset_id); | |
H5Sclose(final_dataspace_id); | |
H5Pclose(final_plist_id); | |
H5Fclose(final_file_id); | |
printf("All chunks combined into final file successfully\n"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import h5py | |
import matplotlib.pyplot as plt | |
# Define the path to the combined HDF5 file | |
combined_file_path = "simulation_data.h5" | |
# Open the HDF5 file and read the data | |
with h5py.File(combined_file_path, 'r') as f: | |
data = f['data'][:] | |
# Extract the relevant columns from the data | |
ox = data[:, 0] | |
oy = data[:, 1] | |
oz = data[:, 2] | |
rx = data[:, 3] | |
ry = data[:, 4] | |
rz = data[:, 5] | |
difficulty = data[:, 7] | |
# Create a scatter plot of the points, colored by difficulty | |
fig = plt.figure(figsize=(10, 8)) | |
ax = fig.add_subplot(111, projection='3d') | |
sc = ax.scatter(rx, ry, rz, c=difficulty, cmap='viridis', s=1) | |
# Add color bar to indicate the difficulty levels | |
cbar = plt.colorbar(sc) | |
cbar.set_label('Difficulty') | |
# Set labels and title | |
ax.set_xlabel('X') | |
ax.set_ylabel('Y') | |
ax.set_zlabel('Z') | |
ax.set_title('Visualizing Points with Color-coded Difficulty') | |
# Show the plot | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is what the visualizer looks like.
The file that the generator outputs is ~25mb.