235 lines
7.4 KiB
C
235 lines
7.4 KiB
C
![]() |
#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;
|
||
|
}
|