gochem/c/main.c

235 lines
7.4 KiB
C
Raw Normal View History

2024-09-26 13:50:26 +02:00
#include "debug.h"
#include "elementdata.c"
#include "raylib.h"
#include "sdfparse.c"
#include <complex.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
//------------------------------------------------------------------------------------------
// Types and Structures Definition
//------------------------------------------------------------------------------------------
void drawAtom(Atom atom, Model sphereModel);
void drawBond(Atom atom);
static Mesh GenMeshCustom(void);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(int argc, char *argv[]) {
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 1200;
const int screenHeight = 800;
// Molecule mol = parseSDF("./resources/mol.sdf");
// Molecule mol = parseSDF("./resources/methyl-vinyl-ketone.sdf");
Molecule mol = parseSDF("./resources/sildenafil.sdf");
// normalizeCoordinates(&mol, screenWidth, screenHeight);
int element_count;
Element *elements = parseCSV("resources/periodictable.csv", &element_count);
D printf("Number of atoms: %d\n", mol.num_atoms);
for (int i = 0; i < mol.num_atoms; i++) {
D printf("Atom %d: %s (%.4f, %.4f, %.4f) - neighbours: %d\n", i + 1,
mol.atoms[i].atom_type, mol.atoms[i].x, mol.atoms[i].y,
mol.atoms[i].z, mol.atoms[i].num_neighbours);
}
InitWindow(screenWidth, screenHeight, "LOL dongs");
SetTargetFPS(60); // Set desired framerate (frames-per-second)
Camera3D camera = {0};
camera.position = (Vector3){10.0f, 10.0f, 10.0f}; // Set camera position
camera.target = (Vector3){5.0f, 5.0f, 5.0f}; // Set camera target
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Set camera up vector
camera.fovy = 45.0f; // Set camera field of view
// camera.projection = CAMERA_ORTHOGRAPHIC; // Camera projection
// type
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
int cameraMode = CAMERA_THIRD_PERSON;
// Model sphereModel = LoadModelFromMesh(GenMeshCustom());
Model sphereModel = LoadModelFromMesh(GenMeshSphere(1.0f, 25, 25));
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_ONE)) {
cameraMode = CAMERA_FREE;
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Reset roll
}
if (IsKeyPressed(KEY_TWO)) {
cameraMode = CAMERA_FIRST_PERSON;
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Reset roll
}
if (IsKeyPressed(KEY_THREE)) {
cameraMode = CAMERA_THIRD_PERSON;
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Reset roll
}
if (IsKeyPressed(KEY_FOUR)) {
cameraMode = CAMERA_ORBITAL;
camera.up = (Vector3){0.0f, 1.0f, 0.0f}; // Reset roll
}
if (IsKeyPressed('Z'))
camera.target = (Vector3){0.0f, 0.0f, 0.0f};
UpdateCamera(&camera, cameraMode);
// UpdateCamera(&camera, CAMERA_ORBITAL);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
// Draw atoms
for (int i = 0; i < mol.num_atoms; i++) {
drawAtom(mol.atoms[i], sphereModel);
drawBond(mol.atoms[i]);
}
EndMode3D();
// Print atom coordinates
DrawText("Atom Coordinates:", 20, 20, 20, DARKGRAY);
for (int i = 0; i < mol.num_atoms; i++) {
DrawText(TextFormat("Atom %d: %s (%.4f, %.4f, %.4f) neighbours: %d",
mol.atoms[i].idx, mol.atoms[i].atom_type,
mol.atoms[i].x, mol.atoms[i].y, mol.atoms[i].z,
mol.atoms[i].num_neighbours),
20, 40 + i * 10, 8, DARKGRAY);
// Convenient place to reset the bond drawn flags
mol.atoms[i].bonds_drawn = false;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
free(elements);
UnloadModel(sphereModel);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return EXIT_SUCCESS;
}
void drawBond(Atom atom) {
Color bondColor = GREEN;
for (int j = 0; j < atom.num_neighbours; j++) {
if (!atom.bonds_drawn) {
if (atom.bond_orders[j] == 2) {
bondColor = BLUE;
} else if (atom.bond_orders[j] >= 3) {
bondColor = RED;
}
DrawCylinderWiresEx((Vector3){atom.x, atom.y, atom.z},
(Vector3){atom.neighbours[j]->x,
atom.neighbours[j]->y,
atom.neighbours[j]->z},
0.1f, 0.1f, 20, bondColor);
}
atom.bonds_drawn = true;
}
}
void drawAtom(Atom atom, Model sphereModel) {
Color color;
float radius;
int scalingFactor = 100;
// radius is empirical from
// https://en.wikipedia.org/wiki/Atomic_radii_of_the_elements_(data_page)
if (strcmp(atom.atom_type, "C") == 0) {
color = BLACK;
radius = 70.0f / scalingFactor;
} else if (strcmp(atom.atom_type, "O") == 0) {
color = RED;
radius = 60.0f / scalingFactor;
} else if (strcmp(atom.atom_type, "H") == 0) {
color = LIGHTGRAY;
radius = 25.0f / scalingFactor;
} else if (strcmp(atom.atom_type, "S") == 0) {
color = YELLOW;
radius = 100.0f / scalingFactor;
} else if (strcmp(atom.atom_type, "N") == 0) {
color = BLUE;
radius = 65.0f / scalingFactor;
} else {
color = GRAY;
radius = 25.0f / scalingFactor;
}
DrawModelWires(sphereModel, (Vector3){atom.x, atom.y, atom.z}, radius, color);
}
// Generate a simple triangle mesh from code
static Mesh GenMeshCustom(void)
{
Mesh mesh = { 0 };
mesh.triangleCount = 1;
mesh.vertexCount = mesh.triangleCount*3;
mesh.vertices = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z)
mesh.texcoords = (float *)MemAlloc(mesh.vertexCount*2*sizeof(float)); // 3 vertices, 2 coordinates each (x, y)
mesh.normals = (float *)MemAlloc(mesh.vertexCount*3*sizeof(float)); // 3 vertices, 3 coordinates each (x, y, z)
// Vertex at (0, 0, 0)
mesh.vertices[0] = 0;
mesh.vertices[1] = 0;
mesh.vertices[2] = 0;
mesh.normals[0] = 0;
mesh.normals[1] = 1;
mesh.normals[2] = 0;
mesh.texcoords[0] = 0;
mesh.texcoords[1] = 0;
// Vertex at (1, 0, 2)
mesh.vertices[3] = 1;
mesh.vertices[4] = 0;
mesh.vertices[5] = 2;
mesh.normals[3] = 0;
mesh.normals[4] = 1;
mesh.normals[5] = 0;
mesh.texcoords[2] = 0.5f;
mesh.texcoords[3] = 1.0f;
// Vertex at (2, 0, 0)
mesh.vertices[6] = 2;
mesh.vertices[7] = 0;
mesh.vertices[8] = 0;
mesh.normals[6] = 0;
mesh.normals[7] = 1;
mesh.normals[8] = 0;
mesh.texcoords[4] = 1;
mesh.texcoords[5] =0;
// Upload mesh data from CPU (RAM) to GPU (VRAM) memory
UploadMesh(&mesh, false);
return mesh;
}