const RNRgb& PDBBond:: Color(void) const { // Return color indicated by bond type static const RNRgb colors[PDB_NUM_BOND_TYPES] = { RNRgb(0.3, 0.2, 0.1), RNRgb(1, 0, 0), RNRgb(0, 0, 1), RNRgb(1, 1, 1) }; return colors[type]; }
const RNRgb R2Image:: PixelRGB(int x, int y) const { // Return pixel RGB at (x,y) RNScalar r, g, b; const unsigned char *pixel = Pixel(x, y); switch (ncomponents) { case 1: case 2: r = *(pixel++) / 255.0; g = b = r; break; case 3: case 4: r = *(pixel++) / 255.0; g = *(pixel++) / 255.0; b = *(pixel++) / 255.0; break; default: r = b = g = 0; break; } return RNRgb(r, g, b); }
const RNRgb& PDBChain:: Color(void) const { static const RNRgb colors[8] = { RNRgb(0, 0, 1), RNRgb(1, 0, 0), RNRgb(0, 0.7, 0), RNRgb(0, 1, 1), RNRgb(1, 0, 1), RNRgb(1, 0.5, 1), RNRgb(1, 1, 0.5), RNRgb(0.5, 1, 1) }; return colors[id % 8]; }
int R3Model:: ReadObjFile(const char *filename) { // Open file FILE *fp = fopen(filename, "r"); if (!fp) { RNFail("Unable to open file %s", filename); return 0; } // Determine directory name (for texture image files) char dirname[1024]; strncpy(dirname, filename, 1024); char *endp = strrchr(dirname, '/'); if (!endp) endp = strrchr(dirname, '\\'); if (!endp) strcpy(dirname, "."); else *endp = '\0'; // Read body char buffer[1024]; int line_count = 0; int material_index =-1; RNArray<R2Point *> texture_coords; RNArray<R3TriangleVertex *> verts; RNArray<R3Triangle *> tris; while (fgets(buffer, 1023, fp)) { // Increment line counter line_count++; // Skip white space char *bufferp = buffer; while (isspace(*bufferp)) bufferp++; // Skip blank lines and comments if (*bufferp == '#') continue; if (*bufferp == '\0') continue; // Get keyword char keyword[80]; if (sscanf(bufferp, "%s", keyword) != 1) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Check keyword if (!strcmp(keyword, "v")) { // Read vertex coordinates double x, y, z; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &x, &y, &z) != 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create vertex R3TriangleVertex *vertex = new R3TriangleVertex(R3Point(x, y, z)); verts.Insert(vertex); } else if (!strcmp(keyword, "vt")) { // Read texture coordinates double u, v; if (sscanf(bufferp, "%s%lf%lf", keyword, &u, &v) != 3) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create texture coordinates R2Point *vt = new R2Point(u, v); texture_coords.Insert(vt); } else if (!strcmp(keyword, "f")) { // Read vertex indices int quad = 1; char s1[128], s2[128], s3[128], s4[128] = { '\0' }; if (sscanf(bufferp, "%s%s%s%s%s", keyword, s1, s2, s3, s4) != 5) { quad = 0;; if (sscanf(bufferp, "%s%s%s%s", keyword, s1, s2, s3) != 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } } // Parse vertex indices int vi1 = -1, vi2 = -1, vi3 = -1, vi4 = -1; int ti1 = -1, ti2 = -1, ti3 = -1, ti4 = -1; char *p1 = strchr(s1, '/'); if (p1) { *p1 = 0; vi1 = atoi(s1); p1++; if (*p1) ti1 = atoi(p1); } else { vi1 = atoi(s1); ti1 = vi1; } char *p2 = strchr(s2, '/'); if (p2) { *p2 = 0; vi2 = atoi(s2); p2++; if (*p2) ti2 = atoi(p2); } else { vi2 = atoi(s2); ti2 = vi2; } char *p3 = strchr(s3, '/'); if (p3) { *p3 = 0; vi3 = atoi(s3); p3++; if (*p3) ti3 = atoi(p3); } else { vi3 = atoi(s3); ti3 = vi3; } if (quad) { char *p4 = strchr(s4, '/'); if (p4) { *p4 = 0; vi4 = atoi(s4); p4++; if (*p4) ti4 = atoi(p4); } else { vi4 = atoi(s4); ti4 = vi4; } } // Get vertices R3TriangleVertex *v1 = verts.Kth(vi1-1); R3TriangleVertex *v2 = verts.Kth(vi2-1); R3TriangleVertex *v3 = verts.Kth(vi3-1); R3TriangleVertex *v4 = (quad) ? verts.Kth(vi4-1) : NULL; // Assign texture coordinates if ((ti1 >= 0) && (ti1 < texture_coords.NEntries())) v1->SetTextureCoords(*(texture_coords.Kth(ti1-1))); if ((ti2 >= 0) && (ti2 < texture_coords.NEntries())) v2->SetTextureCoords(*(texture_coords.Kth(ti2-1))); if ((ti3 >= 0) && (ti3 < texture_coords.NEntries())) v3->SetTextureCoords(*(texture_coords.Kth(ti3-1))); if (quad) { if ((ti4 >= 0) && (ti4 < texture_coords.NEntries())) v4->SetTextureCoords(*(texture_coords.Kth(ti4-1))); } // Check vertices if ((v1 == v2) || (v2 == v3) || (v1 == v3)) continue; if ((quad) && ((v4 == v1) || (v4 == v2) || (v4 == v3))) quad = 0; // Create default material, if needed if (material_index == -1) { R3Brdf *brdf = new R3Brdf(RNRgb(0.2, 0.2, 0.2), RNRgb(0.8, 0.8, 0.8), RNRgb(0.0, 0.0, 0.0), RNRgb(0.0, 0.0, 0.0), 0.2, 1.0, 1.0); R3Material *material = new R3Material(brdf, "Default"); materials.Insert(material); RNArray<R3Triangle *> *mat_tris = new RNArray<R3Triangle *>(); material_triangles.Insert(mat_tris); material_index = 0; } // Get material assert(material_index >= 0); R3Material *material = materials.Kth(material_index); // Create first triangle R3Triangle *triangle = new R3Triangle(v1, v2, v3); tris.Insert(triangle); triangle_materials.Insert(material); material_triangles[material_index]->Insert(triangle); // Create second triangle if (quad) { R3Triangle *triangle = new R3Triangle(v1, v3, v4); tris.Insert(triangle); triangle_materials.Insert(material); material_triangles[material_index]->Insert(triangle); } } else if (!strcmp(keyword, "mtllib")) { // Read fields char mtlname[1024]; if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Read materials if (!ReadObjMtlFile(dirname, mtlname)) return 0; } else if (!strcmp(keyword, "usemtl")) { // Read fields char mtlname[1024]; if (sscanf(bufferp, "%s%s", keyword, mtlname) != 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Find material material_index = FindMaterialIndex(materials, mtlname); if (material_index == -1) { fprintf(stderr, "Unable to find material %s at on line %d in file %s", mtlname, line_count, filename); return 0; } } } // Create triangle array triangles = new R3TriangleArray(verts, tris); // Delete texture coordinates for (int i = 0; i < texture_coords.NEntries(); i++) { R2Point *vt = texture_coords.Kth(i); delete vt; } // Close file fclose(fp); // Return success return 1; }
int R3Model:: ReadObjMtlFile(const char *dirname, const char *mtlname) { // Open file char filename[1024]; sprintf(filename, "%s/%s", dirname, mtlname); FILE *fp = fopen(filename, "r"); if (!fp) { RNFail("Unable to open file %s", filename); return 0; } // Parse file char buffer[1024]; int line_count = 0; R3Brdf *brdf = NULL; R2Texture *texture = NULL; R3Material *material = NULL; while (fgets(buffer, 1023, fp)) { // Increment line counter line_count++; // Skip white space char *bufferp = buffer; while (isspace(*bufferp)) bufferp++; // Skip blank lines and comments if (*bufferp == '#') continue; if (*bufferp == '\0') continue; // Get keyword char keyword[80]; if (sscanf(bufferp, "%s", keyword) != 1) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Check keyword if (!strcmp(keyword, "newmtl")) { // Parse line char name[1024]; if (sscanf(bufferp, "%s%s", keyword, name) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create new material texture = NULL; brdf = new R3Brdf(); material = new R3Material(brdf, texture, name); materials.Insert(material); RNArray<R3Triangle *> *mat_tris = new RNArray<R3Triangle *>(); material_triangles.Insert(mat_tris); } else if (!strcmp(keyword, "Ka")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set ambient reflectance if (material && brdf) { brdf->SetAmbient(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Kd")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set diffuse reflectance if (material && brdf) { brdf->SetDiffuse(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Ks")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set specular reflectance if (material && brdf) { brdf->SetSpecular(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Ns")) { // Parse line double ns; if (sscanf(bufferp, "%s%lf", keyword, &ns) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set shininess if (material && brdf) { brdf->SetShininess(ns); material->Update(); } } else if (!strcmp(keyword, "Ni")) { // Parse line double index_of_refraction; if (sscanf(bufferp, "%s%lf", keyword, &index_of_refraction) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set index of refraction if (material && brdf) { brdf->SetIndexOfRefraction(index_of_refraction); material->Update(); } } else if (!strcmp(keyword, "d")) { // Parse line double transparency; if (sscanf(bufferp, "%s%lf", keyword, &transparency) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set opacity if (material && brdf) { brdf->SetOpacity(1 - transparency); material->Update(); } } else if (!strcmp(keyword, "map_Kd")) { // Parse line char texture_name[1024]; if (sscanf(bufferp, "%s%s", keyword, texture_name) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set texture if (material) { char texture_filename[1024]; sprintf(texture_filename, "%s/%s", dirname, texture_name); R2Image *image = new R2Image(); if (!image->Read(texture_filename)) return 0; R2Texture *texture = new R2Texture(image); material->SetTexture(texture); material->Update(); } } } // Close file fclose(fp); // Return success return 1; }
/* Source file for the R3 light class */ /* Include files */ #include "R3Graphics.h" /* Public variables */ R3DirectionalLight R3null_directional_light; R3DirectionalLight R3default_directional_light(R3Vector(0.0, 0.0, -1.0), RNRgb(1.0, 1.0, 1.0), 1.0, TRUE); /* Class type definitions */ RN_CLASS_TYPE_DEFINITIONS(R3DirectionalLight); /* Public functions */ int R3InitDirectionalLight() { /* Return success */ return TRUE; }