1 /****************************************************************************
4 Copyright (c) 2001 Jerome Jacovella-St-Louis
8 ****************************************************************************/
11 bool CreateCylinder(Mesh mesh, int radius, int height, int steps, DisplaySystem displaySystem)
15 if(mesh.Allocate({ vertices = true, normals = true, texCoords1 = true }, steps * 2, displaySystem))
17 PrimitiveGroup group = mesh.AddPrimitiveGroup({ triStrip, true }, 0);
21 Vector3Df *pVertices, *pNormals;
24 pVertices = mesh.vertices;
25 pNormals = mesh.normals;
26 pTexCoords = mesh.texCoords;
29 group.nVertices = steps * 2;
31 for(c = 0; c<steps; c++)
34 Radians theta = (2 * Pi * c) / (steps - 1);
37 pVertices[index].x = (float)sin(theta) * radius;
38 pVertices[index].y = -height/2;
39 pVertices[index].z = (float)cos(theta) * radius;
41 pNormals[index].x = (float)sin(theta);
42 pNormals[index].y = 0;
43 pNormals[index].z = (float)cos(theta);
47 pVertices[index].x = (float)cos(theta) * radius;
48 pVertices[index].y = -height/2;
49 pVertices[index].z = (float)sin(theta) * radius;
51 pNormals[index].x = (float)cos(theta);
52 pNormals[index].y = 0;
53 pNormals[index].z = (float)sin(theta);
55 pTexCoords[index].x = ((float) c) / (steps - 1);
56 pTexCoords[index].y = 1;
60 pVertices[index].x = (float)sin(theta) * radius;
61 pVertices[index].y = height/2;
62 pVertices[index].z = (float)cos(theta) * radius;
64 pNormals[index].x = (float)sin(theta);
65 pNormals[index].y = 0;
66 pNormals[index].z = (float)cos(theta);
69 pVertices[index].x = (float)cos(theta) * radius;
70 pVertices[index].y = height/2;
71 pVertices[index].z = (float)sin(theta) * radius;
73 pNormals[index].x = (float)cos(theta);
74 pNormals[index].y = 0;
75 pNormals[index].z = (float)sin(theta);
77 pTexCoords[index].x = ((float) c) / (steps - 1);
78 pTexCoords[index].y = 0;
88 public class DNABox : Mesh
90 int width, height, depth;
92 bool Create(DisplaySystem displaySystem)
95 if(Allocate({ vertices = true, texCoords1 = true }, 24, displaySystem))
98 Vector3Df vertices[24] =
100 { -(float)width/2,-(float)height/2,-(float)depth/2 },
101 { (float)width/2,-(float)height/2,-(float)depth/2 },
102 { (float)width/2, (float)height/2,-(float)depth/2 },
103 { -(float)width/2, (float)height/2,-(float)depth/2 },
104 { -(float)width/2,-(float)height/2, (float)depth/2 },
105 { (float)width/2,-(float)height/2, (float)depth/2 },
106 { (float)width/2, (float)height/2, (float)depth/2 },
107 { -(float)width/2, (float)height/2, (float)depth/2 },
109 { -(float)width/2,-(float)height/2,-(float)depth/2 },
110 { (float)width/2,-(float)height/2,-(float)depth/2 },
111 { (float)width/2, (float)height/2,-(float)depth/2 },
112 { -(float)width/2, (float)height/2,-(float)depth/2 },
113 { -(float)width/2,-(float)height/2, (float)depth/2 },
114 { (float)width/2,-(float)height/2, (float)depth/2 },
115 { (float)width/2, (float)height/2, (float)depth/2 },
116 { -(float)width/2, (float)height/2, (float)depth/2 },
118 { -(float)width/2,-(float)height/2,-(float)depth/2 },
119 { (float)width/2,-(float)height/2,-(float)depth/2 },
120 { (float)width/2, (float)height/2,-(float)depth/2 },
121 { -(float)width/2, (float)height/2,-(float)depth/2 },
122 { -(float)width/2,-(float)height/2, (float)depth/2 },
123 { (float)width/2,-(float)height/2, (float)depth/2 },
124 { (float)width/2, (float)height/2, (float)depth/2 },
125 { -(float)width/2, (float)height/2, (float)depth/2 }
127 Pointf texCoords[24] =
129 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
130 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
131 { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
132 { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
133 { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
134 { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
138 // up, front, down, back, right, left
147 memcpy(this.vertices, vertices, sizeof(vertices));
148 memcpy(this.texCoords, texCoords, sizeof(texCoords));
150 group = AddPrimitiveGroup(triangles, 36);
153 memcpy(group.indices, indices, sizeof(indices));
159 UnlockPrimitiveGroup(group);
167 public class DNAHelix : Mesh
177 bool Create(DisplaySystem displaySystem)
180 PrimitiveGroup group;
181 uint16 num = (uint16)(curveSegments*numCurves);
182 int vertexCount = (num+1)*4;
184 if(Allocate({ vertices = true, texCoords1 = true }, vertexCount, displaySystem))
191 int polygonCount = ((num*4)+2);
194 for(v=0, segment=0; segment<num+1; segment++)
196 angle=segment*2*Pi/curveSegments+start;
197 x=(float)(cos(angle)*(radius-width/4));
198 y=(float)(sin(angle)*(radius-width/4));
200 texCoords[v].x = (float)segment / (num + 1) * 16;
202 vertices[v++] = { -x,-(float)height/2+segment*(float)height/num, y };
203 texCoords[v].x = (float)segment / (num + 1) * 16;
204 texCoords[v].y = 0.25f;
205 vertices[v++] = { -x,-(float)height/2+segment*(float)height/num+width, y };
208 for(segment=0; segment<num+1; segment++)
210 angle=segment*2*Pi/curveSegments+start;
211 x=(float)(cos(angle)*(radius+width/4));
212 y=(float)(sin(angle)*(radius+width/4));
214 texCoords[v].x = (float)segment / (num + 1) * 16;
215 texCoords[v].y = 0.75f;
216 vertices[v++] = { -x,-(float)height/2+segment*(float)height/num, y };
217 texCoords[v].x = (float)segment / (num + 1) * 16;
218 texCoords[v].y = 0.50f;
219 vertices[v++] = { -x,-(float)height/2+segment*(float)height/num+width, y };
222 group = AddPrimitiveGroup(triangles, polygonCount * 6);
231 group.indices[index++] = p*2+1;
232 group.indices[index++] = p*2+3;
233 group.indices[index++] = p*2+2;
234 group.indices[index++] = p*2+2;
235 group.indices[index++] = p*2;
236 group.indices[index++] = p*2+1;
238 group.indices[index++] = p*2+startv;
239 group.indices[index++] = p*2+2+startv;
240 group.indices[index++] = p*2+3+startv;
241 group.indices[index++] = p*2+3+startv;
242 group.indices[index++] = p*2+1+startv;
243 group.indices[index++] = p*2+startv;
245 group.indices[index++] = p*2+startv+1;
246 group.indices[index++] = p*2+startv+3;
247 group.indices[index++] = p*2+3;
248 group.indices[index++] = p*2+3;
249 group.indices[index++] = p*2+1;
250 group.indices[index++] = p*2+startv+1;
252 group.indices[index++] = p*2;
253 group.indices[index++] = p*2+2;
254 group.indices[index++] = p*2+startv+2;
255 group.indices[index++] = p*2+startv+2;
256 group.indices[index++] = p*2+startv;
257 group.indices[index++] = p*2;
261 group.indices[index++] = startv;
262 group.indices[index++] = startv+1;
263 group.indices[index++] = 1;
264 group.indices[index++] = 1;
265 group.indices[index++] = 0;
266 group.indices[index++] = startv;
268 group.indices[index++] = 2*num;
269 group.indices[index++] = 2*num+1;
270 group.indices[index++] = 2*num+startv+1;
271 group.indices[index++] = 2*num+startv+1;
272 group.indices[index++] = 2*num+startv;
273 group.indices[index++] = 2*num;
278 UnlockPrimitiveGroup(group);
286 static const char * names[7] = { "Adenine", "Cytosine", "Guanine", "Thymine", "Phosphate", "Desoxyribose", "Hydrogene" };
288 public class DNAModel : Object
293 int helixCurveSegments;
299 int desoxyriboseWidth;
300 const char * textureFile;
303 bool Create(DisplaySystem displaySystem)
308 InitializeMesh(displaySystem);
314 Object phosphate, hydrogen;
316 DNABox box { width = baseWidth, height = baseHeight, depth = baseDepth };
317 // TOFX: Warning this didn't do what I expected: (Neither did a watch on 'rotation'!)
318 //DNAHelix helix { start = 0, height = (numBases-1)*space, numCurves = (float)(numBases * rotation / 360), curveSegments = helixCurveSegments,
319 DNAHelix helix { start = 0, height = (numBases-1)*space, numCurves = (float)(numBases * (double)rotation / 360), curveSegments = helixCurveSegments,
320 radius = hydrogenWidth + baseWidth + desoxyriboseWidth, width = helixWidth };
322 map.Load(textureFile ? textureFile : ":texture1.pcx", null, null);
324 for(c = 0; c < 7; c++)
326 material = { name = CopyString(names[c]) };
327 displaySystem.AddMaterial(material);
330 material.diffuse = material.ambient = white;
331 material.opacity = 1;
334 material.baseMap = displaySystem.GetTexture(names[c]);
335 if(!material.baseMap)
337 material.baseMap = Bitmap { };
338 material.baseMap.Allocate(null, 64, 64, 0, map.pixelFormat, true);
339 if(map.pixelFormat == pixelFormat8)
340 CopyBytesBy4(material.baseMap.palette, map.palette, 256);
341 material.baseMap.Grab(map, 0, c*material.baseMap.height);
342 material.baseMap.MakeMipMaps(displaySystem);
343 displaySystem.AddTexture(names[c], material.baseMap);
346 if(!strcmp(names[c], "Phosphate"))
347 material.flags.tile = true;
353 //******************* Base Meshes *******************
356 helix.ApplyMaterial(displaySystem.GetMaterial("Phosphate"));
358 //******************* PHOSPHATE *******************
359 phosphate = { mesh = helix }; AddName(phosphate, "Phosphate01");
360 phosphate = { mesh = helix }; AddName(phosphate, "Phosphate02");
361 phosphate.transform.orientation = Euler { yaw = 180 };
363 //******************* HYDROGENE *******************
364 hydrogen = { }; AddName(hydrogen, "Hydrogene");
365 hydrogen.InitializeMesh(null);
366 CreateCylinder(hydrogen.mesh, hydrogenWidth/2, numBases*space, 50, null);
367 material = displaySystem.GetMaterial("Hydrogene");
368 material.flags.doubleSided = true;
369 hydrogen.mesh.ApplyMaterial(material);
370 //******************************************************
374 for(c=0; c<numBases; c++)
376 Object base, desoxyribose;
381 int b1 = GetRandom(0,3);
383 Quaternion angle { 1,0,0,0 };
388 angle.Yaw(-rotation*c);
389 matrix.RotationQuaternion(angle);
391 position = { (baseWidth+hydrogenWidth)/2.0f,-numBases*space/2.0f+space/2.0f+c*space,0 };
393 //******************* BASES *******************
394 sprintf(name, "Base%02d", c*2);
395 base = { }; AddName(base, name);
396 base.flags = { mesh = true };
398 base.transform.orientation = angle;
399 base.transform.scaling = { 1,1,1 };
400 base.matrix.Identity();
401 pos.MultMatrix(position, matrix); base.transform.position = pos;
402 base.UpdateTransform();
403 base.material = displaySystem.GetMaterial(names[b1]);
405 sprintf(name, "Base%02d", c*2+1);
406 base = { }; AddName(base, name);
407 base.flags = { mesh = true };
409 base.transform.orientation = angle;
410 base.transform.scaling = { 1,1,1 };
411 base.matrix.Identity();
412 position.x = -(baseWidth+hydrogenWidth)/2.0f;
413 base.UpdateTransform();
414 pos.MultMatrix(position, matrix); base.transform.position = pos;
415 base.material = displaySystem.GetMaterial(names[b2]);
417 //******************* DESOXYRIBOSE *******************
418 sprintf(name, "Desoxyribose%02d", c*2);
419 desoxyribose = { }; AddName(desoxyribose, name);
420 desoxyribose.mesh = box;
421 desoxyribose.transform.orientation = angle;
422 desoxyribose.transform.scaling = { (float)desoxyriboseWidth / baseWidth, 1,1 };
423 position.x = baseWidth+(desoxyriboseWidth+hydrogenWidth)/2.0f;
424 pos.MultMatrix(position, matrix); desoxyribose.transform.position = pos;
425 desoxyribose.material = displaySystem.GetMaterial("Desoxyribose");
427 sprintf(name, "Desoxyribose%02d", c*2+1);
428 desoxyribose = { }; AddName(desoxyribose, name);
429 desoxyribose.mesh = box;
430 desoxyribose.transform.orientation = angle;
431 desoxyribose.transform.scaling = { (float)desoxyriboseWidth / baseWidth, 1,1 };
432 position.x = -baseWidth-(desoxyriboseWidth+hydrogenWidth)/2.0f;
433 pos.MultMatrix(position, matrix); desoxyribose.transform.position = pos;
434 desoxyribose.material = displaySystem.GetMaterial("Desoxyribose");
436 transform.scaling = { 1,1,1 };
437 transform.orientation = { 1, 0,0,0 };
440 if(Merge(displaySystem))
443 SetMinMaxRadius(true);