Jump to content
  • Advertisement
    1. Past hour
    2. tyree

      run attack

      dodge run attack https://youtu.be/9HZ1q4EGWWI
    3. Today
    4. Tedson Santos

      [Play My Game] Rise of Ages 0.9d

      Hey Folks!!! We have a great news for you, we just released a Demo that is our last version of the game before the Early Access on Steam! This is Version 0.9d. The game had several modifications, We hope you like it! Download Link: http://playriseofages.com/demo-0-9d/
    5. This line already gives the angle, so no need to calculate magnitude later. But that's just an optimization. Pretty sure the NaN happens here if angle is zero: So you would need to return identity quaternion if angle is close to zero before that.
    6. Yesterday
    7. 3dBookman

      The 3D book

      After a break of several years the 3D book project is back on. A few short words now on what this blog is about. I have to deliver my wife to the bus station in a few minutes, then a week alone so may have the time then to explain things. But the 3D book is something I started in 014 and put several years into, then the break, now on again. A win32 app with a text window and an ogl window. I just remembered I had something written on this so here it is I write to see if anyone in this community of game developers, programmers, enthusiasts, may be interested in a project I have been developing[off and on] for several years now. So follows a short description of this project, which I call the 3D-Book project. The 3D-Format Reader: A new format of media. Imagine opening a book, the left page is conventional formatted text - on the right page a 3D animation of the subject of the text on the left hand page. The text page with user input from mouse and keyboard, the 3D page with user intput from a game pad. An anatomy text for a future surgeon, with the a beating heart in 3D animation. A children's story adventure book with a 3D fantasy world to enter on the right page. ... Currently 3D-Format Reader consists of a C++ Windows program: Two "child" windows in a main window frame. Two windows: a text-2D rendering window and a 3D-rendering window. The text-2D window, as its' name implies, displays text and 2D graphics; it is programmed using Microsoft's DirectWrite text formatting API and Microsoft's Direct2D API for 2D graphics. The 3D-rendering window uses the OpenGL API. A 3DE-Book page is formatted in one of two possible modes: DW_MODE or GL_MODE. In GL_MODE both windows are shown; the text-2D rendering window is on the left and the 3D OpenGL window is on the right. In DW_MODE, only the text-2D rendering window is shown, the OpenGL window is hidden (Logically it is still there, it has just been given zero width). The 3D-Format Reader reads text files, which consists of the text of the book, control character for the formatting of text, (bold, underline, ...), display of tables, loading of images(.jpg .png ...), and control of 2D and 3D routines. 3D-Reader programming is based on a Model-View-Controller (MVC) architecture. The MVC design is modular: The Controller component handles user input from the operating system , the Model component processes the input, and the View component sends output back to the user on the display. Typical Parent-Child windows programs have multiple "call back" window procedures(winProcs): One for the parent window and one for child window. The MVC model, simplifies message routing by using a call-back window procedure which receives Windows messages for the main window, the text-2D window and the OGL window. A sample MVC program by Song Ho Ahn was used as a template for the 3DE-Reader. Rushed for time now, so a hasty sign off and thanks for reading. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 8 - 21 -18 I spent the last few days working on procedural mesh generation. First looking to find a bit of code to do what I had in mind. Which begs the question: What did I have in mind? I just wanted a cube mesh generator such that... Requirements Input: An integer n = units from origin to cube face. Output: The vertices for a unit cube centered on the origin. 8n² triangles per cube face. 3 times 8n² verts in clockwise winding order (from the outside of the cube) ready for the rendering pipeline. Screenshot of some cubes generated with the procedural cube mesh generator. That was about it for the output requirements. I did not want to hand code even a single vertex and did not want to load a mesh file. I was sure the code was out there somewhere, but was not finding it. So, a bit reluctantly at first, I started coding the mesh generator. I started enjoying creating this thing and stopped searching for the "out-there-somewhere" code; although still curious how others did this. Analysis First question: How do we number the verts? It would be great to conceive of some concise algorithm to put out the cube face verts all in clockwise order for the outside faces of the cube directly. That seemed beyond me so I plodded along step by step. I decided to just use a simple nested loop to generate the cube face verts and number them in the order they were produced. The hope(and the presumption) was: The loop code was in some order, running thru the x y and z coordinates in order, from -n to +n, therefore the output would be a recognizable pattern. The simple nested loop vert generator did not let us down: It gave us a recognizable pattern, at least for this face. It turned out (as expected now) that all six faces have similar recognizable patterns. Plotting the first row or two of verts you can easily see how to run the rest of the pattern. Plot of the first(of six) cube faces verts output by the vert generator: Input of n: There are (2n+1)² verts per cube face, or 25 verts for n = 2. This is looking at the x = -n face from the outside of the cube. To simplify the math it helps to define s = 2n. Then there are (s + 1)² verts, or 25 for s = 4 s² cells on the face, or 16 for 4 = 2. We are going divide each cell into 2 triangles, so there are 2s² triangles per face, or 32 for s = 4. Second question: What pattern for the triangles? How to number the 2s² = 32 triangles? What we want in the end is a bit of code such that... for triangles T[0] thru T[2s²-1] or T[0] thru T[31]( for n = 4), we have T[N] = f0(N), f1(N), f2(N). Where f0(N) gives the first vertex of T[N] as a function of N. and f1 and f2 give the second and third verts, all in CW winding order looking into the cube of course. Here the choice is a bit arbitrary, but it would seem to make things easier if we can manage to have the order of triangles follow the order of verts to a degree. Numbering the triangles. And now the problem becomes: Look at the triangle vert list, T0 - T8...T31 in the image, and try to discern some pattern leading us to the sought after functions f0(N), f1(N), f2(N) where N is the number of the triangle, 0 thru 2s²-1. This really is the holy grail of this whole effort; then we have T[N] = f0(N), f1(N), f2(N) and that list of verts can be sent directly to the rendering pipeline. Of course we want these functions to work for all six faces and all 12s² triangles to cover the cube. But first let's see if we can just do this one face, 0 thru 2s²-1.. Thru a bit of trial and error the 32 triangles(T0 - T31) were ordered as shown. Now we have an ordered list of the triangles and the verts from our loop. T0 = 0 5 6 T1 = 6 1 0 T2 = 1 6 7 T3 = 7 2 1 T4 = 2 7 8 T5 = 8 3 2 T6 = 3 8 9 T7 = 9 4 3 T8 = 5 10 11 ... T30 T31. If we can find a pattern in the verts on the right side of this list; we can implement it in an algorithm and the rest is just coding. Pattern recognition: It appears T2 = T0 with 1 added to each component T3 = T1 with 1 added to each component In general T[N+2] = T[N] with 1 added to each component, until we come to T8 at least. Also it is hard to recognize a relation between the even and odd triangles,To see what is happening here it helps to look at an image of the generalized case where n can take on any integer value n > 0. Looking for patterns in this generalized(for any n) vert plot we see... We have defined s = 2n. The 4 corner coordinates(+-n,+-n) of the x = - n cube face, one at each corner (+-n,+-n). There are (s+1)² verts/face numbered (0 thru (s+1)² -1). There are 2s² triangles/face numbered (0 thru 2s² -1). They are indicated in red. It's not as bad as it looks iff you break it down. Let's look at the even triangles only and just the 0th vert of these triangles. For any row we see the number of that first vert of the even triangles just increases by one going down the row. We can even try a relation such as T[N].0 = N/2. Here T[N].0 denotes the 0th vert of th Nth triangle. Which works until we have to jump to the next row. Every time we jump a row we T[N+1].0 = T[N].0 + 2 for the first triangle in the higher row. So we need a corrective term to the T[N].0 = N/2 relation that adds 1 every time we jump a row. We can use computer integer division to generate such a term and N/2s is such a term. It only changes value when we jump rows and we get our first function ... f0(N) = N/2 + N/2s. (even triangles) Remember the integer division will discard any remainder from the terms and check this works for the entire cube face, but only for the even triangles. What about the odd triangles? Going back to the triangle vs vert list for the specific case n = 2, s = 4 for the first row; we see for the odd triangles T[N].0 = T[N-1].0 + s + 2. And adding this term, s + 2 to the formula for the even triangle 0th vert we get f0[N] for the odd triangles. f0(N) = N/2 + N/2s + s + 2. (odd triangles) Continuing this somewhat tedious analysis for the remaining functions f1(N), f2(N) we eventually have these relations for the x = -n cube face triangles. for N = 0 thru N = 2s² - 1. defining m = N/2 + N/2s. T[N] = m, m + s + 1, m + s + 2 T[N] = f0(N), f1(N), f2(N). (even N) T[N] = m + s + 2, m + 1, m T[N] = f0'(N), f1'(N), f2'(N) (odd N) So it turns out we have two sets of functions for the verts, fn(N) for the even triangles and fn'(N) for the odd. To recap here; we now have formulae for all the T[N] verts as functions of N and the input parameter n: Input: An integer n = units from origin to cube face. But this is only for the first face x = -n, we have five more faces to determine. So the question is: Do these formulae work for the other faces? And the answer is no they do not, but going through a similar analysis for the remaining face gives similar T[N] = f0(N), f1(N), f2(N) for them. There is still the choice of how to number the remaining triangles and verts on the remaining five faces, and the f0(N), f1(N), f2(N) will depend on the somewhat arbitrary choice of how we do the numbering. For the particular choice of a numbering scheme I ended up making, it became clear how to determine the f0(N), f1(N), f2(N) for the remaining faces. It required making generalized vert plots for the remaining five face similar to the previous image. Then these relation emerged... For face x = -n T[N] N(0 thru 2²-1) we have the f0(N), f1(N), f2(N), even and odd For face x = n T[N] N(2s² thru 4s²-1) add (s+1)² to the x=-n face components and reverse the winding order For face y = -n T[N] N(4s² thru 6s²-1) add 2(s+1)² to the x=-n face components and reverse the winding order For face y = n T[N] N(6s² thru 8s²-1) add 3(s+1)² to the x=-n face components For face z = -n T[N] N(8s²0 thru 10s²-1) add 4(s+1)² to the x=-n face components For face z = n T[N] N(10s²0 thru 12s²-1) add 5(s+1)² to the x=-n face components and reverse the winding order And these are enough to allow us to write explicit expressions for all 12n² triangles for all 6 faces T[N] and what remains to be done is to implement these expression in code. Which turned out to be a much simpler task than finding the f0(N), f1(N), f2(N) and resulted in a surprisingly short bit of code. Implementation I have attempted to make this C++ snippet of code as generic as possible and have removed any dev-platform specific #includes and the like. GLM, a C++ mathematics library for graphics developed by Christophe Riccio is used. It is a header only library. https://github.com/g-truc/glm/releases/download/ That is the only outside dependency. // Procedural cube face verticies generator #include <vector> #include <glm/gtc/matrix_transform.hpp> struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle }; /* std::vector<Triangle> cube_Faces(int n) Input: integer 'n'; the units from origin to cube face. Output: vector<Triangle> glTriangle; container for the 12*(2*n)² triangles covering the 6 cube faces. */ std::vector<Triangle> cube_Faces(int n){ size_t number_of_triangles(12*(2*n )*(2*n)); size_t number_of_face_verts(6*(2*n +1 )*(2*n+1)); std::vector<glm::vec3> face_verts(number_of_face_verts); std::vector<Triangle> glTriangle(number_of_triangles); // Generate the 6*(2n +1 )² face verts ------------------------------- int l(0); for(int i = 0; i < 6; i++){ for(int j = -n; j <= n; j++){ for(int k = -n; k <= n; k++){ // Below "ifS" strip out all interior cube verts. if( i == 0){ // do yz faces face_verts[l].x = (float)(-n); //x face_verts[l].y = (float)j; //y face_verts[l].z = (float)k;}//z if( i == 1){ // do yz faces face_verts[l].x = (float)(n); //x face_verts[l].y = (float)j; //y face_verts[l].z = (float)k;}//z if( i == 2){ // do zx faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)(-n); //y face_verts[l].z = (float)k;}//z if( i == 3){ // do zx faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)(n); //y face_verts[l].z = (float)k;}//z if( i == 4){ // do xy faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)k; //y face_verts[l].z = (float)(-n);}//z if( i == 5){ // do xy faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)k; //y face_verts[l].z = (float)(n);}//z l++; } } } // Generate the 12*(2*n)² triangles from the face verts ------- int s = 2*n; int q = 2*s*s; int a = (s+1)*(s+1); int f(0); int r(0); int h(0); for( int N=0; N < number_of_triangles; ){ // triangles already in CW winding if( N < q || N < 5*q && N > 3*q - 1 ){ // do the even indicies f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; glTriangle[N].vert[0] = face_verts[h]; glTriangle[N].vert[1] = face_verts[s + 1 + h]; glTriangle[N].vert[2] = face_verts[s + 2 + h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; // do the odd indicies glTriangle[N].vert[0] = face_verts[s + 2 + h]; glTriangle[N].vert[1] = face_verts[ 1 + h]; glTriangle[N].vert[2] = face_verts[h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; } // triangles needing reverse order for CW winding if( N > 5*q - 1 || N < 3*q && N > q - 1 ){ // do the even indicies glTriangle[N].vert[0] = face_verts[s + 2 + h]; glTriangle[N].vert[1] = face_verts[s + 1 + h]; glTriangle[N].vert[2] = face_verts[h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; // do the odd indicies glTriangle[N].vert[0] = face_verts[h]; glTriangle[N].vert[1] = face_verts[1 + h]; glTriangle[N].vert[2] = face_verts[s + 2 + h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; } } // Normalize the cube to side = 1 ------------------------------ for(int i = 0; i < number_of_triangles; i++){ glTriangle[i].vert[0].x = glTriangle[i].vert[0].x/(2.0*(float)n); glTriangle[i].vert[0].y = glTriangle[i].vert[0].y/(2.0*(float)n); glTriangle[i].vert[0].z = glTriangle[i].vert[0].z/(2.0*(float)n); glTriangle[i].vert[1].x = glTriangle[i].vert[1].x/(2.0*(float)n); glTriangle[i].vert[1].y = glTriangle[i].vert[1].y/(2.0*(float)n); glTriangle[i].vert[1].z = glTriangle[i].vert[1].z/(2.0*(float)n); glTriangle[i].vert[2].x = glTriangle[i].vert[2].x/(2.0*(float)n); glTriangle[i].vert[2].y = glTriangle[i].vert[2].y/(2.0*(float)n); glTriangle[i].vert[2].z = glTriangle[i].vert[2].z/(2.0*(float)n); }; return glTriangle; } The rendering was done using OpenGl. // OGL render call to the cube mesh generator - PSUEDOCODE int n(2); int cube_triangle_Count = (12*(2*n)*(2*n)); std::vector<Triangle> cube_Triangles(cube_triangle_Count); cube_Triangles = cube_Faces(n); glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]); glBufferData(GL_ARRAY_BUFFER, cube_Triangles.size()*sizeof(Triangle), &cube_Triangles[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0); glEnableVertexAttribArray(0); glDrawArray(GL_TRIANGLES,0,3*cube_triangle_Count); This just gets the position attribute of the cube face triangle verts; for the color and other attributes there are a couple of options: Use separate GL_ARRAY_BUFFERS for the color and other attributes. Or add attributes to the Triangle struct... struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle attribute1; attribute2; ... }; Screenshot of the spherified cube. What's next? Now that we have the cube mesh what we can do with with it practically unlimited. The first thing I did was turn it into a sphere. Playing with tesselating the cube or sphere or stellating it with different patterns; might do. Ended up trying a few matrix transformations on the cube mesh. These are shown in the image below. These shapes are result short bits of code like the code for the column shape below. //Column for(int i = 0; i < number_of_triangles; i++){ for(int j = 0; j < 3; j++){ if( glTriangle[i].vert[j].y < 0.5f && glTriangle[i].vert[j].y > -0.5f ){ float length_of_v = sqrt((glTriangle[i].vert[j].x * glTriangle[i].vert[j].x) + (glTriangle[i].vert[j].z * glTriangle[i].vert[j].z)); glTriangle[i].vert[j].x = 0.5f*glTriangle[i].vert[j].x/length_of_v; glTriangle[i].vert[j].z = 0.5f*glTriangle[i].vert[j].z/length_of_v; } } } Doing this; the blacksmith at his forge analogy soon presents. The mesh is the ingot, hammer matrices stretch, round and bend it against the fixed geometry of the anvil - coordinate system. I am the smith. Tetrahedron The tetrahedron is the platonic solid with the least number of faces(4), edges(6), and verts(4). In antiquity it was associated with the element of fire due to its' sharp vertices. The algorithm for the tetrahedron mesh was developed in a similar way to the cube, but here it seemed simpler to get a routine for just one face - an equilateral triangle - and use matrix translations and rotations to form the complete tetrahedron. So more like origami or tinsmithing than blacksmithing. Procedural tetrahedron screenshot. The n = 4 and the general case To get an routine for the general case, n an integer > 0, a bit of what I think is known as mathematical induction was used. PSUEDO-CODE Algorithm to generate equilateral triangle face with unit side composed of n² "sub-triangle" in the xy plane. std::vector<Triangle> equilateral(int n){ std::vector<Triangle> tri_Angle(n²); // Create the seed triangle in xy plane . // This is triangle "0" in the image above. // This is in the xy(z=0) plane so all the // tri_Angle.vert[0 thrue n -1 ].z = 0. // We just work with the x and y verts. tri_Angle[all].vert[all].z = 0; // The seed triangle tri_Angle[0].vert[0].x = 0; tri_Angle[0].vert[0].y = 0; tri_Angle[0].vert[1].x = 1/2n; tri_Angle[0].vert[1].y = sin(π/3)/n; tri_Angle[0].vert[2].x = 1/n; tri_Angle[0].vert[2].y = 0; // Build the equilateral triangle face. int count(0); for(int row = 0; row < n; row++){ count = 0; Spin = glmRotateMatrix( π/3, zaxis ); // The magic happens here! for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++) { if (count % 2 == 0 ) // Triangle is even in the row - just translate { // more magic. x_Lat = glm_Matrix((count + row)/2n, row*sin(π/3)/n, 0.0f); tri_Angle[i].vert[0] = x_Lat* tri_Angle[0].vert[0]; tri_Angle[i].vert[1] = x_Lat* tri_Angle[0].vert[1]; } else // Triangle is odd in the row - rotate then translate { //and more magic. x_Lat = glm_Matrix((count + row + 1)/2n, row*sin(π/3)/n, 0.0f); tri_Angle[i].vert[0] = x_Lat*Spin*tri_Angle[0].vert[0]; tri_Angle[i].vert[1] = x_Lat*Spin*tri_Angle[0].vert[1]; } } count++; } return tri_Angle; } This is the psuedocode version of the routine which generates the verts for the n² triangles in a face. Getting this algorithm was a bit of a brain drain but looking for patterns in the image of the face allowed it to happen. We use a "seed" triangle, which is triangle 0 on the lower left of the figure. The verts of this one triangle are input; the rest of the n² triangles verts are generated by translating and rotating this seed triangle. Notice: There are n rows, every row has 2 less triangles than the row below. If we number the triangles from 0 to 2n - 2*row - 2, where the rows run 0 to n; the even triangles just need to be translated ... in the x direction by (count + row)/2n where count = their position in the row 0 to 2n - 2*row - 2. in the y direction by row*height. height = height of seed triangle. The odd triangles need to be rotated pi/3 = 60 degrees around the z axis then translated ... in the x direction by (count + row + 1)/2n where count = their position in the row 0 to 2n - 2*row - 2. in the y direction by row*height. height = height of seed triangle. Now we have a single face for the tetrahedron, to join the four faces together we need the angle between the faces called the dihedral angle. Dihedral Angle Each of the five platonic solids has a characteristic called the dihedral angle. This is the angle between the faces. For the cube it is 90 degrees or pi/2 radians. For the tetrahedron it is 70.528779° = arccos(1/3) = atan(2*sqrt(2)); The tetrahedron, with just four faces, is the simplest of the platonic solids. The simplest way I can think of to build it: Start with the four face stacked one on another, edges aligned. Imagine the top three faces each hinged to the bottom face along one edge. Then rotate each face around then hinged edge by arccos(1/3), the dihedral angle. That is the method of the bit of code shown below. vector<Triangle> tetrahedron(int N){ std::vector<Triangle> tetra(4n²); tetra[all].vert[all].z = 0; // The seed triangle tetra[0].vert[0].x = 0; tetra[0].vert[0].y = 0; tetra[0].vert[1].x = 1/2n; tetra[0].vert[1].y = sin(π/3)/n; tetra[0].vert[2].x = 1/n; tetra[0].vert[2].y = 0; // ----- The first face ----- // generate the first equilateral triangle face with unit side // composed of n² "sub-triangle" in the xy(z=0) plane. int count(0); for(int row = 0; row < n; row++) { count = 0; Spin = glmRotateMatrix( π/3, zaxis ); for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++) { if (count % 2 == 0 ) // Triangle is even in the row - just translate { x_Lat = glm_Matrix((count + row)/2n, row*sin(π/3)/n, 0.0f); tetra[i].vert[0] = x_Lat* tetra[0].vert[0]; tetra[i].vert[1] = x_Lat* tetra[0].vert[1]; } else // Triangle is odd in the row - rotate then translate { x_Lat = glm_Matrix((count + row + 1)/2n, row*sin(π/3)/n, 0.0f); tetra[i].vert[0] = x_Lat*Spin*tetra[0].vert[0]; tetra[i].vert[1] = x_Lat*Spin*tetra[0].vert[1]; } } count++; } // ----- The second face ----- // generate the second equilateral face from the first // by rotating around the X axis by the dihedral angle. float tetra_Dihedral = atan(2*sqrt(2)); Spin = glmRotateMatrix( -tetra_Dihedral, xaxis ); //just rotate for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[n² + i].vert[j] = Spin*tetra[i].vert[j]; } } //The rotation gives CCW verts so need need to make them CW again for(int i = n²; i < 2n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // ----- The third face ----- // For the second face we rotated the first triangle around its' // base on the X - axis. For the third face we rotate the first // triangle around its' edge along the vector ( 0.5, 0.866025, 0.0 ). Spin = glmRotateMatrix( tetra_Dihedral ,glm::vec3(0.5f,0.866025f,0.0f)); for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[2n² + i].vert[j] = Spin*tetra[i].vert[j]; } } //need to make it CW again for(int i = 2n²; i < 3n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // ----- The forth face ----- // For the forth face we first translate the original face along the // X axis so it right edge vector (-0.5f, 0.866025f, 0.0f) passes thru the origin. // Then we rotate the first triangle around the that vector by the dihedral angle. x_Lat = glm::translate( glm::vec3(-1.0f, 0.0f, 0.0f)); Spin = glmRotateMatrix( -tetra_Dihedral, glm::vec3(-0.5f,0.866025f,0.0f)); for(int i = 0; i < n²; i++) { for(int j = 0; j < 3; j++) { tetra[3n² + i].vert[j] = Spin*x_Lat*tetra[i].vert[j]; } } //need to make it CW again for(int i = 3n²; i < 4n²; i++) { swap(tetra[i].vert[0] ---- with --- tetra[i].vert[2]; } // We now have the complete tetrahedron, tetra(4n²), but its' base // is not horizontal so let's make is so. // put the base in the xz plane // rotate 90 - dihedral angle around X axis. Spin = glm::rotate( tetra_Dihedral - half_PI, xaxis); for(int i = 0; i < 4n²; i++) { for(int j = 0; j < 3; j++) { tetra[i].vert[j] = Spin*tetra[i].vert[j]; } } // We now have the complete tetrahedron, tetra(4n²), sitting with its' // base on the xz(y=0) plane, let's put its' center at the origin. // For this we need another Platonic Solid attribute: The radius of // the tetrahedrons circumscribed sphere which is sqrt(3/8). So the // center of the tet is this vertical distance down from its' apex. // To put the center at the origin we need to translate down this // distance along the Y axis. We need also to xlat along the Z axis // by 1/2(sqrt(3)) = 0.28867; the distance from the center of a face // to the center of a side. // Finally we need to center along the X axis( xlat -.5) x_Lat = glm::translate( glm::vec3(-0.5f, -sqrt(3/8), sqrt(3)/2); for(int i = 0; i < 4n²; i++) { for(int j = 0; j < 3; j++) { tetra[i].vert[j] = x_Lat*tetra[i].vert[j]; } } return tetra; } Notes: Oops: Left out std::vector<Triangle> tri_Angles(4*n*n); Should be the first line of the function body! Corrections to the corrections: First line of function definition vector<Triangle> tetrahedron(int N){ should be vector<Triangle> tetrahedron(int n){ Those last two for loops could and probably should be combined to do a translate*rotate*triangle in one statement, but I have not tried it. All distances are for a tetrahedron with unit side. The sign of the dihedral angle in the rotations was usually determined by trial and error. I.e.; I tried one sign, compiled the code and rendered the tet. If it was wrong I just reversed the sign. The end result is a tetrahedron with its' center at the origin, its' base in the xz plane, and one edge parallel to the X axis. Of the five platonic solids; three (tetrahedron, octahedron, icosahedron) are composed of equilateral triangle faces. One of square faces (cube). And one of pentagon faces (dodecahedron). Two tetrahedrons fit nicely in a cube. 11-16-18: Corrections to code blocks for equilateral triangle and tetrahedron. 11-18-18: More corrections. Icosahedron Two faces = Icosahedron Petal Five petals in this flower = 10 faces = half of the icosahedron 12-5-18 Understanding the icosahedrons' 3d form via 2d images is difficult; we need to make a small, palm sized, 3d model. It takes nineteen paper triangles and some tape. The vertices of five equilateral triangles must come together at each vertex of the icosahedron. The icosahedron has 20 faces and 12 verts, but leaving one face off the model allows us to look in side. Besides; when where done we'll have a neat little icosahedron basket. You don't really need to make a model to code the icosahedron; but it helped me to see some properties which simplified its' construction. Symmetries are important to the mathematician and perhaps even more so to the physicist. They say something has a certain symmetry if you perform a certain operation on it and the world remains unchanged. Unchanged in the sense that you can not even detect something has been done to it. Example: Rotate a square 90 degrees around its' center in the plane. The square has that type of rotational symmetry. The square also has an inversion symmetry; if you take every point on the square and invert it through the origin you end up with the same square you started with. Inversion is simply negating all the coordinates. The center must be at the origin of course. This is true for the cube, but not for the tetrahedron. Symmetries simplify the construction (coding) of an object. Going back to the cube; it might have been easier to do three faces and then just invert them thru the origin to get the other three. For the tetrahedron simple inversion is not a symmetry, but I am pretty sure inversion together with a rotation is. If so; we could do two faces and then perform an inversion - rotation on them in one step. And inversion in Cartesian coordinates just means to negate all the verts - easy! Toying with our icosahedron model; holding it gently with our thumb on one vertex and our middle finger on the opposite vertex, lazily twirling it around an imaginary axis through those two vertices; we are struck with a thought: We are toying with our icoshedron model twirling it around an axis through - Eureka! - two opposite vertices: The icosahedron has inversion symmetry. This is great - our work has just been cut in half. We can code half of the icosahedrons verts and just invert(negate) to get the rest. Thank you inversion symmetry. But let's not stop now, we are on a roll (no pun intended); lets see if we can find more symmetries to make our work easier. Looking intently; holding our model as before, but still, not rotating. Then slowly rotating about the axis we see another symmetry. After one fifth of a revolution(2π/5 radians) the universe is the looks the same as when we started rotating it. The icosahedron has a 2π/5 rotational symmerty. Can we use this to cut our work load? You bet we can. First we need to clear up a few points about something central to our construction efforts: The axis of symmetry. (Sorry, the puns just keep coming.) An axis of symmetry is a line passing thru two opposite vertices and the center of the icosahedron. The icosahedron has six of them: We only need one. We will use the Z axis. Dihedral angle: To be precise, it is the angle between the normals of two adjacent faces. The images: Looking at the images we see a flower shape with five "petals". A petals is just two faces joined along a side. The angle between the two petal faces is the icosa's dihedral angle; arccos(- √5/3) radians. Five petals make a "flower" , which is ten faces, so it is half of the icosahedron. Once we have five petals joined to make this flower, we just copy/invert all its' verts to get the other half: We have our icosahedron. The Plan: Refer to the figures 1.) Make a petal. 2.) Attach one tip of the petal the axis of symmetry. (Oriented properly of course.) 3.) Copy/rotate the petal around the axis of symmetry by 2π/5 radians four times to get five petals = a flower. We are using the 2π/5 radians rotational symmetry here. 4.) Copy/invert( r -> -r ) our five-petal-ten-face flower to get our 20 face icosahedron. Using inversion symmetry here. So just four steps; sounds simple enough. Each step has its own steps of course, but they are mostly intuitive common sense things we must do to get the result. Constants: Before we get to the code we need four constants. 1.) The dihedral angle between two faces, the dihedral_angle. dihedral_angle. = arccos(- √5/3) = 46.06322 radians = 138.18969°. 2.) The angle between the Z axis and the normal of a face of a petal at the vertex. 0.652351 radians 3.) The radius of a circumscribed sphere(A sphere that touches all 12 verts). In other words the distance from the icosahedron center to a vertex. Also called the circumradius. R = sin(2π/5). 4.) The rotational symmetry: 2π/5 radians Let's not do a blow by blow, or should say, a bend by bend, description of the code. If a picture is worth a thousand words, it seems safe to assume an animated 3D image is worth even more. I suggest we compile the code and render to the display step by step. In fact this is how the code was developed; with a projection matrix and a rotation around the Z axis. Compile - Render the first face: F0. " " the first petal: P0 from F0 and F1. " " the second petal P1. " " the third petal P2. " " the fourth petal P3. " " the fifth petal P4. We now have the flower. Compile - Render the inversion of the flower. Done. The icosahedron psuedocode. struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle }; //PSUEDOCODE ICOSAHEDRON /* input: integer n - number of triangles along icosahedron edge. output: std::vector<Triangle> icosahedron - mesh with 20n² triangles. */ std::vector<Triangle> icosahedron( int n ){ const float dihedral_Angle = acos(-(sqrt(5.0f)/3.0f)); const float dihedral_Comp = π - dihedral_Angle; std::vector<Triangle> T_icosahedron(20n²); // Create the seed triangle T. Triangle T; T.vert[0].x = 0; T.vert[0].y = 0; T.vert[0].z = 0; T.vert[1].x = 1/2n; T.vert[1].y = sin(π/3); T.vert[1].z = 0; T.vert[2].x = 1/n; T.vert[2].y = 0; T.vert[2].z = 0; // ----- F0 ----- // Create the first face; "F0" in the xy(z=0) plane // from the seed triangle T. int count(0); for(int row = 0; row < n; row++){ count = 0; for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++){ if (count % 2 == 0 ){ // Triangle is even in the row - just translate . x_Lat = glm::translate(count+row)/2n, row*sin(π/3), 0); for(int j = 0; j < 3; j++){ T_icosahedron[i].vert[j] = x_Lat*T.vert[j]; } } else{ // Triangle is odd in the row - rotate then translate. x_Lat = glm::translate( glm::vec3((count+1+row)/2n, row*sin(π/3), 0)); Spin = glm::rotate( π/3, zaxis ); for(int j = 0; j < 3; j++){ T_icosahedron[i].vert[j] = x_Lat*Spin*T.vert[j]; } } count++; } } // At this point comment out the rest of the code, // return T_icosahedron; // Compile and render F0 to the display. // ----- P0 ----- // Create the first petal "P0" in the xy(z=0) plane. glm::vec3 axis(0.5f, sin(π/3), 0.0f); Spin = glm::rotate( π/3, zaxis ); //just rotate Spin2 = glm::rotate( -dihedral_Comp, axis ); for(int i = 0; i < n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[n² + i].vert[i] = Spin2*Spin*T_icosahedron[i].vert[j]; } } // xlate P0 by -1.0 along x and bend down by epsilon from the xy plane // epsilon is the angle we want between the Z axis and the normal of F0. // epsilon = 0.6523581f; x_Lat = glm::translate( glm::vec3(-1.0f, 0.0f, 0.0f)); Spin2 = glm::rotate( glm::mat4(1.0), -π/3, zaxis ); Spin = glm::rotate( glm::mat4(1.0), -epsilon, xaxis ); //just rotate for(int i = 0; i < 2n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i].vert[j] = Spin*Spin2**x_Lat*T_icosahedron[i].vert[j]; } } // At this point comment out the rest of the code, // return T_icosahedron; // Compile and render P0 to the display. // Create P1 from the P0 verts, rotate 2π/5 around z then Spin = glm::rotate( 2π/5, zaxis ); //just rotate for(int i = 0; i < 2n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i+2n²].vert[j] = Spin*T_icosahedron[i].vert[j]; } } // At this point comment out the rest of the code, // return T_icosahedron; // Compile and render P0 - P1 to the display. // Create P2 thru P4 from P0 verts: rotate around z: // 2*2π/5 for P2, 3*2π/5 for P3 and finally 4*2π/5 for P4 // P2 Spin = glm::rotate( 2*2π/5, zaxis ); //just rotate for(int i = 0; i < 2n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i+4n²].vert[j] = Spin*T_icosahedron[i].vert[j]; } } // P3 Spin = glm::rotate( 3*2π/5, zaxis ); //just rotate for(int i = 0; i < 2n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i+6n²].vert[j] = tSpin*T_icosahedron[i].vert[j]; } } // P4 Spin = glm::rotate( 4*2π/5, zaxis ); //just rotate for(int i = 0; i < 2n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i+8n²].vert[j] = Spin*T_icosahedron[i].vert[j]; } } // At this point we should have the full flower. // Comment out the rest of the code, // return T_icosahedron; // Compile and render P0 thru P4 to the display. // Move everthing up along z to put the icosahedron center at the origin. // radius of circumscribed sphere = sin(2π/5), for face side = 1. x_Lat = glm::translate( glm::vec3(0, 0, sin(2π/5)); for(int i = 0; i < 10n²; i++){ for(int j = 0; j < 3; j++){ T_icosahedron[i].vert[j] = x_Lat*T_icosahedron[i].vert[j]; } } // invert all the verts and reverse for cw winding // this creates the other half of the icosahedron from the first 10 triangles for(int i = 0; i < 10n²; i++){ for(int j = 0; j < 3; j++){ // invert T_icosahedron[i+10n²].vert[j].x = -T_icosahedron[i].vert[j].x; T_icosahedron[i+10n²].vert[j].y = -T_icosahedron[i].vert[j].y; T_icosahedron[i+10n²].vert[j].z = -T_icosahedron[i].vert[j].z; } // Swap verts 0 and 2 to get back to CW winding. hold = T_icosahedron[i+10n²].vert[0];// reverse T_icosahedron[i+10n²].vert[0] = T_icosahedron[i+10*n²].vert[2]; T_icosahedron[i+10n²].vert[2] = hold; } return T_icosahedron; // Spherify - uncomment the code below to spherify the icosahedron /* for(int i = 0; i < 20n²; i++){ for(int j = 0; j < 3; j++){ float length_of_v = sqrt( (T_icosahedron[i].vert[j].x * T_icosahedron[i].vert[j].x) + (T_icosahedron[i].vert[j].y * T_icosahedron[i].vert[j].y) + (T_icosahedron[i].vert[j].z * T_icosahedron[i].vert[j].z)); T_icosahedron[i].vert[j].x = T_icosahedron[i].vert[j].x/length_of_v; T_icosahedron[i].vert[j].y = T_icosahedron[i].vert[j].y/length_of_v; T_icosahedron[i].vert[j].z = T_icosahedron[i].vert[j].z/length_of_v; } } */ return T_icosahedron; } Screen-shots: First petal P0 and five petal icosahedron flower.
    8. knsl96

      Constraining rotation to a single axis

      Thanks for your reply! Your solution seems to be working but i'm having some problems to implement it. Sometimes (depending on the axis/angle of the user input) the final quaternion has some NaN components. Here's my code (MyVector class is similar to Vector3, and MyQuaternion similar to Unity quaternion): public MyQuaternion ConstrainedRotate(float userX, float userY, float userZ, float userAngle, float axisX, float axisY, float axisZ) { MyVector controllerAxis = new MyVector(userX, userY, userZ); MyVector rv = new MyVector(controllerAxis._x * userAngle, controllerAxis._y * userAngle, controllerAxis._z * userAngle); MyVector constraintAxis = new MyVector(axisX, axisY, axisZ); constraintAxis.Normalize(); float dprod = constraintAxis.Dot(constraintAxis, rv); MyVector constrained_rv = new MyVector(constraintAxis._x*dprod, constraintAxis._y*dprod, constraintAxis._z*dprod); float angle = constrained_rv.Magnitude(); //Vector3.length() MyVector axis = new MyVector(constrained_rv._x / angle, constrained_rv._y / angle, constrained_rv._z / angle); MyQuaternion quat = new MyQuaternion(axis, angle); return quat; }
    9. WitchLord

      `asCContext::CallScriptFunction` called with null

      Fixed in revision 2569. Regards, Andreas
    10. Edward Tagg

      Lets make a video game! - Project 16x16

      Wouldn't let me send you a request on Discord for some reason, so I'll leave mine: LetMeDoStuff#5728 I'd be happy to throw in some ideas when there's more info, but we can discuss that in Discord anyway
    11. Major update to the post format, bumping!
    12. Lauren Tuccy

      Totally new to this and having a hard time

      This was me, wrong google account. That’s embarrassing
    13. jbadams

      Actual logical code theory resources

      Surprised no one has mentioned the freely available Game Programming Patterns yet - it may be a bit on the advanced side based on your description, but it's a great resource. Amit Patel's Introduction to A* and Implementation of A* pages provide good very visual explanations of that algirithm. Is that the sort of thing you're looking for?
    14. Jack Simmons

      Totally new to this and having a hard time

      Thank you guys for your advice, I have tried both unity and unreal, and I think unreal is going to be my best bet. I guess I am just going to have to start smaller, which is good advice in itself.
    15. Stephcraft

      Lets make a video game! - Project 16x16

      You can contact me on Discord for more details on the audio style, my username is : Stephcraft#9845 You can also contact me on Discord, I'd be glad to work with you. Also you can write your story idea in the folder named idea of the GitHub repository in the file of your choice : .txt .md .docx etc...
    16. printf("Hello %s", "follow game makers!"); I'm about to make a game engine, and looking for advice! Background I have a game engine project I've been thinking about A LOT lately. I know it's gonna be hard, in fact the most challanging programming challange i can think of. With that said, I'm willing to put down the time and effort. I'm looking for some advice to keep the project up and running and I'm asking you, game makers! I've so much passion about this project. I've tried making a game engines before, but they have all halted. Some failed because of lack of focus, some failed because of unorganised structure, some failed because of lack of experiance, too big scope, unclear destination... you get the point. Now I'm taking a different approach. I'm doing the boring part, pre-planning, researching, etc. That's partly why I'm here, asking you. I'll lay out my plan for you guys. Prerequisites I'm gonna try to keep technical terms to a minimum. So no spoiling what graphical API's or libraries I'm going to use, that's just asking for political warfare. This is more about the project management, avoiding pitfalls and such. The engine is gonna be a 2D engine. When i feel finished (probably in a couple of years) I will expand to 3D, but that's for another time. Because it's a game engine it should handle any type of 2D game, sidescrolling, top-down, hell even click-adventures! Disclaimer Sorry if my english is a bit wacky. Don't judge! The Game list(You'll read about it soon.) is just for experience purpose. I don't wanna fall in any kind of legal action because i stole some idea and thus only for personal use. My own ÜBER-awesome-final-game, if ever completed, will be released to the public. I first posted this on stackoverflow and was shutdown pretty hard because of too broad topic, understandable. Hoping this is the right forum, I'm just looking for some friendly advice. Kinda hard to get on this internet thingamabob... The Plan Start simple, work my way towards a more and more advanced game engine. In the end and my long term goal is my very own advanced 2D game(of course built on my engine). As a bonus, I might release the sourcecode of the game engine if I'm happy how it turned out. I believe in short term goal too keep my motivation and the feel of progress. But also have major goals to strive for, too always keep myself challanged, get bits and pieces to be proud of and most important have something to look forward to. Some of my older tries failed because i lost focus and stopped coding for a while. This time around i think it's best to atleast get a few lines of code every week. My "average goal" is to code for atleast a couple of hours every weekend. Just so i don't stop coding, the worst pitfall (i think). My strategy is a list of games to make on my journey. Trying to always have the list as a unit testing tool (Surely I'll have to redo older games when my engine gets up to speed). The list looks a bit like this. Game list, Major hits 1. Pong 2. 1 Level platformer (Extremly restricted) 3. Extended 1 level platformer with screenscrolling, jumping, etc. 4. Same level with added Sprite/Animation. 5. Same level with Goomba-like enemies and a finish line. 6. Multiple levels! 7. Super Major. A complete, short, single player mario-like game, with different enemies, levels and of course a boss. 8. Top down 2D game. Bomberman-like 9. Bomberman-like multiplayer 10. ... This goes on for a while. Some smaller games, some Super Major Smaller technical milestones to start with (I know i said "no technical talk", but this is the extent of it) 101. Graphical window (Ok, it's not a game but i have to start somewhere right?) 102. Draw a triangle [Draw objects] 103. Pong, very hardcoded (No help from the game engine to make collision or so) First game PONG 201. Textures 202. Simple physics (gravity, friction) collision 203. Player Controller 204. ... First Platformer: Have a 1 Level platformer were i can jump onto objects and stuff. No enemies, no screenscrolling. Just a super simple platformer. 301. Animation 302. Add Screenscrolling 303. Static enemies 304. Super simple AI. (Move toward player) 305. ... Keep on adding so i can complete my list of games This is of course not the full list, i just don't want to TL;DR.. If you are still here, you are the GREATEST! Some concerns The more I complete games on my list, the longer it will take to complete the next one. The more powerful function, the longer it will take. Multiplayer for instance, is no easy task... ADVICE Am i on the right track? Would you do something different? What do you think will work, what is risky? Have you tried making a game engine yourself? What kind of pitfalls did you encounter?
    17. Xerophyte

      Audio for an abstract motorbike racing game

      Hiya, I have some cool idea for background music as well as sound effects for the video. I have been making electronic music for over half my life, but lately have been wanting to branch out into game sound design, and learn more about that world. For example, I can come up with sounds for an electric engine, and provide a range of upcycle, downcycle, break, accelerate etc noises, which I assume could then be implemented into the engine to trigger when appropriate? I'm curious how that is done smoothly, although I do know there are various ways, not all of them are on the programmers' side. I'm here to watch and learn as much as participate. I am still working on a website and portfolio; but you can hear my music on soundcloud as /phytophile, /neuroqueer, and most recently /xerophyte. I have 18+ years electronic music experience, and nearly my whole life with theory and rhythm, feel free to DM me if you want to discuss anything further, and at this point I'm just looking to get involved more than I am looking to get paid. Your game looks like it would be a lot of fun to make SFX and/or music for, even if just a couple contributions. Regards, Xerophyte Greetings; I am interested as an electronic musician looking to get into sound design how these programs work between the audio and the game engine - does development have to be done simultaneously, or can they be used on the programmers end to further integrate and smooth the sound in-game? I primarily use Cubase as a sequencer, and would like to save for Nuendo which has scripting and game-related integrations built in, but I am not quite at that stage yet. If you could point me towards some resources I would greatly appreciate it. I understand the idea of adaptive audio, and how to create certain types, but as I am not a programmer that is about where my practical understanding stops. Anyway thanks for the time if you get a chance.
    18. I have a diagnosed math disability and I really struggled with PreCalculus this semester. I know I won't be doing much with Calculus as software engineer because I don't want to be involved professionally with a game company. I think I have the ability to pass the course, but it takes me a very long time to study and resultingly leaves me very little time to study for my other classes. This makes it very difficult for me to keep up my GPA. I tend to only get "passing" grades in Math subjects regardless. Also, I have to attend full-time because of the requirements for the Financial Aid I need to have to pay for college. Computer Science majors need to attend both Calculus 1 and Calculus 2. The Computer Science Department in my college doesn't allow us to make our own custom degrees. However, I do want to continue making games as a hobby. I want to be able to learn how to do fairly "fancy" things like create procedurally-generated worlds, and I want to have at least some ability to create AI for monsters and such. My question is, knowing this, should I see if I can get a waiver for Calculus 1 and 2?
    19. Xerophyte

      Looking to start a team

      I just joined these forums looking around for small projects to contribute to, as I build up an audio engineering and sound design portfolio (I have been working with all kinds of synthesis, audio sampling/editing, engineering and mixing for my own music production for about 18 years, and am looking to branch out). Not necessarily looking for paid work at the moment, so that is just fine; more to get a taste for what it is like to work-to-order, work with a team, etc. Could also do some scoring, timing to video, maybe foley stuff and the like.
    20. One way to do it: If the user input is a quaternion, convert it to axis and angle. Convert axis and angle to a rotation vector: vec3 rv = axis * angle Project this vector to your constraint axis unit vector: vec3 constrained_rv = constraintAxis * constraintAxis.Dot(rv); Then convert result back to axis / angle: float angle = constrained_rv.Length(); vec3 axis = constrained_rv / angle; Then convert to quat or matrix or whatever you need: quat q; q.FromaxisAndAngle(axis, angle); So that's quite simple. I assume everything is given in global space, otherwise perform the operations in the local space of the joint for example. Ask if there's something unclear...
    21. I would like to be part of the team but am not fond of Discord. I understand it would be hard to communicate with the team if not using Discord but I'm willing to communicate here or by e-mail. It gives me the same "stay away" gut feeling Facebook did and I didn't join in that craze, so as far as I'm concerned I'm batting 1000 there and not trying to ruin my streak. I have worked in call centers and have been complemented on my voice as well and would like to try voice acting, this seems like a good place to get my foot in the door and get started on a portfolio. Aside from that if you'd be willing to work with someone not using Discord I can offer my assistance with 2d art, textures and game design. I understand 3d modeling and textures although I haven't worked in 3d since the mid 00's in high school, but they did save my blocky house that I made there as an example of what you could do with the software to show classes for a few years after so I understand the concepts. I have the newest version of Unity and am able to navigate it, I just haven't used it too much because I am a complete novice at code and GMS is friendlier to code illiterate people and you can edit the scripts in the software. The work I have saved on this computer and can show is admittedly very cartoony although that is the look I've been trying to work on and polish but I am more than willing to try my hand at more realistic looking things, I think textures would be a good place to start. I can also help with GUI, fonts, logos, etc.
    22. deltaKshatriya

      Totally new to this and having a hard time

      What are you currently using for this project? It sounds like you have something already. Are you doing this in 2d or in 3d? From what I found out about Inform, it seems like it's not using its own language. So just based on what you've written, some starting points for you will be: 1): If you haven't selected what you will build this project with, you need to do that first. You'll need a 2d/3d game engine, depending on what you're building. Some popular engines are Unreal and Unity3d. Beyond a point it won't matter what you pick, so long as you feel comfortable with it. 2): Once you've selected an engine, you'll need to learn how to program in the language the engine uses. You'll then need to learn how to build basic things in that engine. Some people start with basic games like pong in 2d. With some engines, even getting a basic FPS type first person view camera and character controller can be quick as well (Unity3d does this really easily, and I'm sure Unreal has something similar) 3): Now comes the fun part. Break your project into smaller pieces that you can solve. The visuals would be one part, i.e. designing assets etc (or buying, if you don't want to spend time making 2d/3d assets). Controls could be another piece. Stats could be another. View your project as a series of smaller tasks and you'll find it makes much more sense to start building it that way. And remember: Rome wasn't built in a day. Take your time, and don't expect wonders in one day, keep building up to your project, and one day you'll look back and realize how much you've accomplished. Hope this helps, and good luck!
    23. I've spent the last two years programming in Assembly and C for retro computers such as the ZX Spectrum and Megadrive, and OOP just did not make sense there at all. One quickly learns - the hard way - that memory is a rare commodity and processing power is almost limited to addition and subtraction, with multiplication and division coming in at a very high premium... Your program and its functions( or in an object's case "methods" ) need to be split into data preparation and processing, in a top-to-bottom fashion. Calling even a single function can sometimes bring the program to its knees in terms of performance - local variables and passing data are not free-of-charge where memory is concerned. And code...boy it takes far more code to do even the simplist of things... Returning to OOP is like Marty McFly returning to 1985 - we have an abundance of processing power and memory, and boy are you glad to have kickass sound and graphics hardware to match! We missed you 3D soooo much! But because we visited the past, we now understand how sloppy we have been with OOP in the present - treating objects like primatives, and creating them on the fly during method calls that are being called during a game loop... I can say this with 100% confidence; if you spend time learning a structured language( C for arguments sake ) on limited hardware, alongside your OOP, then you will not go wrong with OOP. For giggles, I was interrogated as to why I was using C instead of Assembly for ZX Spectrum programs. It was very much like how this thread has played out!
    24. A game I think deserves an honorable mention here is Tactics Ogre: Let Us Cling Together. Basically it's like Game of Thrones without the gratuitous sex scenes but it came out about a decade prior to the first book and I have a sneaking suspicion George R.R. Martin played this game at some point in the 90's. The story is based loosely on the Yugoslav wars and the music of Queen and the game play is solid. The same team changed the story to be more War of the Roses/Crusades themed and polished the game play a bit to make the game's spiritual squeal, Final Fantasy Tactics which is also a great game, but in my opinion Tactics Ogre is better, and the SNES/PSX version is better than the PSP re-release, the dialogue feels more natural and less like they are going for the faux-medieval feel. There really are questions about right and wrong and the paths of "lawful" and "chaotic" aren't really just place holders for "good" and "evil" but an examination on what extent states should go to when fighting one another and even where the moral line is when states fight non-state entities. It's really deep for a game that came out in 1995 but it manages to not be preachy, it just is what it is. Everyone has the potential to be a monster in this game It's one of the first games to give an actual branching story although it is somewhat limited and leads to the same end boss there are different actions you can take that will give different endings. I am going to avoid spoilers just in case anyone wants to play the game themselves but I will leave a link to one of the multiple ending scenes. It's a clip of the PSP version but it still holds up. Just in case the link doesn't work the scene starts at 15:00. I think this is how GoT is going to end at which point my theory will be confirmed.
    25. Espillier

      Actual logical code theory resources

      oops, sorry, got bugged by my phone
    26. Bolt-Action Gaming

      This Week in GameGuru - 12/10/2018

      Welcome back to another busy week in the GameGuru community. Let's dive right in! Official GameGuru News This week saw another model kit update - specifically PBR getting added to some of the collectibles and minor doodads of the Sci-Fi kit. I did notice, however, they are still using the Red Cross on the collectible for the heathkit. This is considered a no-no in the GameDev community since it violates the Geneva Convention for using the international symbol of the Red Cross. I brought this to TGC's attention and while no comment has been given thus far on it I'm certain they will take quick and decisive action to remedy this. As we enter the traditional holiday cycle, don't be surprised to not see any major code releases or updates done for a while. I've noticed we tend to get 3-4 major releases a year and the most recent one will probably hold us for a while, likely until March or so. In the interim, it appears they are content to continue pushing Add On content and updates. It can be frustrating for users who want to see steady and complete refinement of the core product. Well hey, at least it's consistent, right? What's New in the Store Recently a TGCStore seller's discord was added. If you need access, contact 'TheNext' on the regular GameGuru discord. Not a lot of brand new stuff, though it seems the cartoon-style assets are really taking off. I like how they look though I worry it's going to saturate the market a bit. Still, Reliquia and Belidos both are providing really quality stuff you can find right off the main store page. There's also a creepy Nun and an 'abomination' by Gtox. Free Stuff In 2016 , there was a great bit of 'Christmas Giving' done at Wolf's signalling. I have to say, it was a nice sentiment and I would love to see more of that. In the meantime, enjoy this 'free little alien'. If you're looking for Wolf's Christmas Advent Calendar of free stuff from 2016, check it out at this link here! Third Party Tools and Tutorials Well foremost it appears that Epic games is positioning themselves as an indie gamedev marketplace. This is huge news and deserves some praise. Steam is a great platform in a lot of respects but the 30% right off the top is pretty brutal for many involved. Epic is offering a digital platform with 12% costs, but get this - if you use the Unreal engine then the traditional 5% for using that engine will be deducted from the 12% they take. So you in reality are saving money by using their engine on their platform. Pretty brilliant marketing though they'll need more than that to defeat a monster as big as Steam. Also it appears that SegmentAutoWelder (an FPSC conversion tool for GG) is repaired. You can get your updated copy here: https://forum.game-guru.com/thread/220102 Random Acts of Creativity (WIPs) Well, interestingly enough as work slows down on the engine, work picks up on people's projects! Lots of interesting screenies for this week for you. I hope I caught them all! Mstockton's in development PBR Assets Bonesy continues work on his Sci-Fi Shooter DuchenKuke is putting out some fantastic Metro:2033 style screenshots Len the man continues to show us how simple methods produce great results for cutscenes VincentHendricks made this great scene using some dynamic lights set at the right coloration! Friskon - Lotgd made this bizarre gif which sort of boggles and fascinates simultaneously! As you can see, there's a lot going in in the community. I'm still waiting for a serious game to show up, something that can really knock the socks off other communities out there. I think if guys like Duchenkuke can keep working at it, they'll eventually release something incredible. It just takes perseverance, some tolerance for GameGuru's nuances, and a steady hand. Beyond that we're seeing some amazing work by the other devs who contribute code wise. Check out some of the latest works of Graphix and Amenmoses - their particle system now has physics effects! T-bone is working on stealth mechanics similar to what you find in the old Thief games: Video Here Amenmoses has made some huge advances to his 'pickuppable' scripts. Notably now you can actually use them to throw and injure enemies. Check out the video of it here: https://vimeo.com/305258044 In My Own Works This week I didn't get as much done as I'd like. The last mile here is proving somewhat difficult as I saved all the more dangerous or difficult tasks to cover for last. This means particles, physics, advanced engine tricks like camera control - all of that is a bit daunting to write and a lot to research and test. It'll get there though. The trick is to just keep plodding inexorably forward. View the full article
    27. thanks... you have been very helpful
    28. Tom Sloper

      Pay What You Want Model

      Locking thread (necro).
    29. Not all collections can be modified, and only some iterators are suitable for insertion. The standard library provides iterator types like insert_iterator and output iterators, which are being revised somewhat in C++20. There is also an inserter template you can use, with common adapters like front_inserter and back_inserter. With your container objects a and b, you could use std::copy( b.begin(), b.end(), std::back_inserter(a)); That will copy all the items in b onto the back of a. To test that out: { std::vector<int> a = { 1, 2, 3 }; std::vector<int> b = { 4, 5, 6 }; // Copy all the items in b onto the back of a std::copy( b.begin(), b.end(), std::back_inserter(a)); for(int x : a) { std::cout << x << std::endl; } } Output is all six values.
    30. DavinCreed

      Totally new to this and having a hard time

      One thing that's always been true for me, no matter complexity of the project or my current mood, is that if a thing seems to big for me to point I don't even know where to start, that means I have to break it into smaller pieces. Design documents help with this, which is why it's commonly suggested. For more specific advice, I'd need more specific information. It sounds like you're going to be making a pretty big leap in complexity from interactive fiction to simulating a magic system while taking into account stats and personality traits. For something like this, a good way to keep motivation and to find better starting places, is to break the whole game up into a little portions like: a spell casting game, then add in a character with stats, then add in going to classes... etc. Taking on something like that as a whole is like staring up at a 2000' cliff and it's extremely daunting. But finding a way up by using 20' cliffs is manageable. Are you going to be using a third party engine or starting completely from scratch? I recommend third party engines, and the best suited one will depend on the project. I prefer UE4, but Unity3D is awesome as well. There are other good ones if you're doing a 2D game.
    31. Hello fellow gamedevs, I need some help with a problem that i can't solve... In my project I have an object that acts as a controller for a robot (the robot is a diferent game object). The user can choose how to rotate this controller (introducing an axis and an angle) and the joints of the robot mirror the controller rotation. The problem is that I want to constrain this given rotation (the axis and the angle that the user chooses on the UI) to make the robot joint move along one single axis (for example, the joint can only rotate around its vertical axis). The only restriction I have in this project is not to use the default Unity vector3/quaternion class, so i'm building my own vector & quaternion class and I need to know how to mathematically solve the problem i've posted. Any kind of help would be gladly appreciated! Thanks!
    32. frob

      License for a Game Engine?

      I get that impression based on the problems he had with each of the licenses and the questions he had: Combined, those statements lead me to believe his big fear is that someone will take his published work, improve on it, and leave him in the dust. With open source software, all the licenses not only permit that type of thing, but for some it is explicitly an incentive to continue producing the best possible code. The Free Software Foundation has four "freedom" goals with the GPL and other licenses, and this ability comes with the fourth Freedom. That is, anybody anywhere can can create a derived product, including marketing that product and charging a distribution fee for that product. They can do it without notifying you of their changes, nor incorporating their changes back into yours. The fourth freedom means somebody else can start with the same product, add features and modify features, and supplant the original creator as the leader for the product.
    33. I agree, with both sentiments. When working in a group or working on a project that has to be maintainable for the unforeseeable future, the whole project should follow a consistent methodology. Bad code is bad code though. Trying to go through poorly written OO code is just as difficult as going through a different poorly written methodology. It all boils down to trying to read the mind of another programmer. That's why documentation is so important, even in OO coding. I'd take a logically structured, consistent, well documented code base that doesn't even meet my ideal conventions any day over a mediocre OO code base. Maybe the reason why some programmers are less inclined towards OOP is that they lean towards a more free-flowing mind and a less structured mind (while others are the reverse)? I've been sent to places to fix someone else's software too so I do understand where the resentment and frustration comes from, but I haven't seen enough examples to say that OOP is clearly better than any other methodology. I've seen chaotic, bloated OO code and equally confusing non-OO code. Bad code is bad code... and good code is good code, no matter what methodology it employs. I suppose when the software industry matures to the point of, say, the housing industry, we'd have "building code" requirements. It might happen one day, but there are so many different languages and coding environments that we're still in the wild west of software development, I feel. Anyway, I'm not an opponent of OOP. I think it's a great methodology. It's easy to build bloat and overly complex dependencies, but when followed rigorously and thoughtfully, it's beautiful... I mean, it's well engineered and maintainable! Sorry, "beautiful" is one of those artsy-fartsy words that "you know who" tend to use. 😉
    34. Hey, nice seeing you again! I can safely say that this update is packing quite a punch, so let's get right to it! Patching up holes First, I want to talk about navigation meshes. Previously, only the procedurally generated floors were included in the navmesh baking process. This meant that all special rooms (aside for landfills and gyms) were completely inaccessible for any NPCs. This was due to two issues. The first one was simply that the navmesh baker only looked for the generated floor rather than any walkable surface. In Unity, it was just a matter of changing things a bit to use a bound box rather than checking in the object's hierarchy. The other issue was the way the floor was generated... Previously, most special rooms using static assets had floors that only covers the room itself, without counting the actual connective gap between it and the rest of the rooms. Because the floors were generated using marching squares, that connection's floor turns into an awkwardly shaped triangle, and thus created two small triangular holes. The problem was fixed by simply adding another square of the floor after that connective square. With these two solutions, NPCs are now able to enter and navigate special rooms, so there's no escape now! New Relics and capacities Next, there's now a lot of newly implemented capacities (and thus relics). Backup Floppy Capacities This relic comes with the Second Chance capacity Second Chance When the player is about to die, then they instantaneously regain 25% of their health. This capacity can only be used once. You can, however, have that capacity many times and thus have multiple chances. Stats Bonuses DEF -35% HP -25% Beach Ball Capacities This relics only has one capacity: Double Jump. Double Jump This capacity is self-explanatory: You can now jump again in mid-air. Stats Bonuses AGL -12% Concentrated ATK Juice Capacities This relics comes with two capacities: Slow Attack and Charge Up Slow Attack This capacity simply slows down the attack speed. It also influences the charging times of chargeable weapons (like bows). This capacity can also be applied multiple times, meaning that attacks get slower and slower the more Slow Attack capacities you have. Charge Up This capacity lends to the wearer the capacity to charge attacks with swingable weapons like swords. A charged attack will have a somewhat substantial damage bonus depending on how long the player held the attack button. Quite useful to deal with stronger enemies! Stats Bonuses ATK +25% AGL -10% Echo Drop Capacities This relic only got one capacity: Shockwave. Shockwave With this capacity, the entity can generate a shockwave when they attack if they're lucky. This makes any enemies in a small radius take damage no matter if they're hidden or not Stats Bonuses DEF -29% Electronic Mask Capacities This relic comes with two capacities: See Enemy Health and Clairvoyance. See Enemy Health This capacity is quite self-explanatory. It gives the player the ability to see any targeted enemy's current health. Quite handy for planning attacks! Clairvoyance This capacity helps the player find their way by rendering a nice glowing path to the exit. The path actually gets refreshed every 5 seconds, and there's even a nice fade-out. Here's a picture of that path As you can see it's really AESTHETIC. The colours of that path are picked from our palette, meaning that it changes colours depending on the current level. Stats Bonuses DEF + 5% HP -20% Fan Of Violence Capacities This relic lends two capacities: Corrosive Spead and Enflamer Corrosive Spead This capacity makes any killed enemies drop a puddle of poisonous blood. If another enemy walks on it they instantaneously become poisoned (if they don't have any other status effect that is). The puddle dries up after a while. As of now, there's no actual damaged dealt directly to enemies when they stand on a puddle. This might an idea for later, though. Enflamer This capacity is quite easy to understand: you now deal fire damages and have a chance to give the burning status to any attacked entities. Stats Bonuses ATK +5% HP -5% Flying Shoe Capacities This relic only got one capacity: Hover. Hover This capacity makes the entity able to glide for a short period of time after a jump. Simply press and hold the jump button to glide. After a bit, the glide will stop. You can also release the jump button during a glide to stop it. One would think that the Double Jump capacity would counteract with this one but one would be wrong: just hold the button down after the double jump. This paired with a ranged weapon will make a deadly combo. Stats Bonuses HP -5% New Activatable Item Next, I want to talk about a new activated Item: French Fried French Fried Alignment: Future Funk Description This is a rather funny looking moustached french fry wearing a beret and smoking a cigarette (Don't smoke, kids). This item can summon a seagull familiar that attacks any nearby enemies for a limited amount of time. Once the time runs out the seagull disappears. The player can have up to 3 seagulls at a time. there's also a cooldown before the item can be used again. Capacities Aside for its activatable ability, the Hover capacity is also given to the player as long as they hold the item. Stats Bonuses DEF -11% Headshots! I've previously thrown the idea around of having different damage bonuses if the player targets a specific body part with a projectile. I'm proud to say that the feature is now fully implemented. Now there's a 5x damage multiplier to projectile if they hit the head (for example). Although these bonuses exist, there's still a lot of balancing to do and whatnot. But I got to say that it's quite fun headshooting enemies with arrows (mainly because enemies aren't balanced yet). This works (of course) for any projectiles. Mouse Refactored There's also have been a big mouse control refactor. Previously, the mouse script I used wasn't as flexible as I originally thought. Rather than coding everything from the ground up, I've decided to cherry-pick code from Unity's standard Assets FirstPersonController script. I Initially wanted to fully use the controller, but there were some input delays with the Update and FixedUpdate functions. I decided to pick its MouseLook script and integrate it into my custom PlayerController. The results were night and day. Not only I could easily change the sensitivity, but there's even a "Smooth Mouse" function which interpolates mouse movements. Mouse Sensitivity Speaking of mouses, I've also added the ability to change the mouse sensitivity. This was made after many feedbacks of my playtesters, who were either unable to use the mouse properly or complained about an excessively sensitive mouse. The Mouse Sensitivity setting takes the form of two components: a slider and an input field. In essence, the input field is used to save the actual sensitivity, while the slider is just a more tactile way to set the sensitivity. Right now, changing the slider will update the input field, which in turns updates the mouse sensitivity. If the player wants an absurd sensitivity (like 100 or something), they can't use the slider for that (which only goes up to 20 right now) and instead have to manually input this in the input field. There's also another checkbox component controlling that previously mentioned "Smooth Mouse" mode. Pause Screen Option Tab Now there's an options tab in the pause menu: This is a quick way to change common settings such as volume slides and mouse sensitivity among other things. These work just like their Main Menu counterparts. Once the player closes the pause menu, options are automatically saved. Quite handy if you want to adjust your mouse sensitivity mid-game, or lowering volumes while streaming. Closed Rooms Previously, all rooms were open form the getgo. The player could technically speedrun their way through the game without breaking a sweat. This kinda made the game quite boring, as there weren't any valid reason to destroy every enemy in each room. This was in a dire need of change. So I've now implemented a linear progression system, in which the player needs to clear the room of any enemy before passing on. Of course, the player can break walls or enter special rooms anytime (mainly because these rooms are optional and won't provide any shortcuts at all), but in order to go to the next room, they need to clean the room first. The way this works is by having closed/opened doors (much like locked doors but without any type of locks). This makes the game feel more like a game, although there's still place for improvement. Minor Upgrades Fixed the MSAA artifact bugs It was quite simple: just use FXAA Technically I can also do TAA (Temporal Anti Aliasing), but this could be put in the options. Of course, there's a lot of other options, but right now FXAA does the job just fine There might be better options, or maybe an MSAA fix but this will wait. Added a looping testing sound effect when fiddling around with the Sound Effect volume slider This is for both the Main Menu's options screen and the Pause Menu Options tab. Fixed a lot of bugs, especially with destruction/creation Charging an attack now slow down the player Once the player unleashes its attack it resets Previously both the Quick and Slow Attack capacities only affected swing speeds. Now they also affect the charging rate. Added a touch of Ambient Occlusion I will probably put this in the options later on... Next Week Even with a cold doing its thing I'm still trying to be proactive and work on the game. In fact, yesterday I started working on a draft of a boss behaviour tree. Although still really rough and full of bugs I think I can have a working boss ready for next week. Afterwards, It'll be modelling time again, but this time it'll be level specific stuff. And after that, there's other relics, items, food, capacities and abilities that are left in the design document that needs to be implemented in the game, which means modelling, coding, designing and whatnot. But right now let's focus on bosses...
    35. The constructor can't take 'var' (var is only allowed for local variables). The new[] {...} determines its type from the values inside the { }. In this case since 10 20 and 30 are int literals, the array will be an int[]. This might be a problem in your byte[] case since I don't believe there is a byte literal syntax yet.
    36. I started learning OO development ages ago from a Pascal and C background, still in Uni, because I felt my code was disorganized and hard to maintain and there must be a better way to do it. I was but a hobbyist back then, doing small projects (tiny even, if compared to many of the things I did later), but there was already enough frustration that I felt compelled to learn a different style of programming. Even for a one-person hobbyist it's still worth it because it really cuts down on complexity of the whole code allowing a single person to tackle far more complex projects and significantly reduces the things a coder needs to remember (or look up later if forgotten) thus reducing forgetfulness bugs as well as time wasted having to rediscover, from the code, shit one did some months before. I strongly recommend you get the original "Design Patterns" book from the gang of four (not the most recent fashion-following me-too patterns books) and read the first 70 pages (you can ignore the actual patterns if you want). It is quite the intro to the Object Oriented Design Principles and, already 20 years ago, it addressed things like balancing the use of polymorphism with that of delegation.
    37. RandNR

      Dread Quest Arena

      Album for Dread Quest Arena
    38. In Archer Voice: You Want to have Spaghetti Code? Cuz that's how you get spaghetti code
    39. timothyjlaird

      Actual logical code theory resources

      Flowchart for Terathon's Tombstone engine: http://tombstoneengine.com/architecture.php
    40. So my only coding experience is with writing Interactive Fiction games with Inform, so I get the logic and stuff, but, I'm so used to starting with a program with libraries and assets already built in, that I have no idea how to build something from scratch. I'm would like to make this simulation game where the player is a student in a [magic] school, and I've got stats for the students, their personality types, and ideas on how that should effect their performance in class, and experience rates, and all this data in a google spreadsheet, but I have NO idea how to start creating this game on a code level. So, I'm just struggling on finding out how to get started. Can anybody give me some advice?
    41. Angry Snail

      Lets make a video game! - Project 16x16

      I've been studying audio for the past 3.5 years, and specifically game audio the past year and a half and would be super up for making some sound effects for this!
    42. Dangerous article. Of course everyone is free to state his/her opinions but I feel like the cost of code maintainance is not taken in consideration at all. As far as I am concerned encapsulation is awesome... and I'm using Verilog those days! Proper code engineering is difficult. I've seen more than a company dominate the competitors thanks to well engineered codebase and more than one company biting the dust under the weight of unmaintaneable code bases.
    43. MobilityWins

      Unity Level Designer needed ASAP

      Hi sorry for the late reply, you can contact me through nathancook53@gmail.com or if you can give me your email I will invite you to the unity collab and you can pull the project
    44. dozd

      Automating the Game

      We know that dispatching the same trains again and again in a loop improves your memory. After a while you exactly know where this train is heading without even clicking on it. We also know that this improving of your memory causes a boredom. That’s where an automation can shine! Four of five dispatchers approve. The automation will be a critical part of the game. We want the player to gradually expand from the starting stations towards the other edges of the game plan. But this move is not possible when she has to dispatch same trains over and over. She may need to return after some time to further improve the operations but not to do the basics things again and again. Read more on our blog: https://railroute.bitrich.info/2018/12/10/automating-the-game/
    45. Release v2.4 is out with explicit resource state transition control, better multi-threading safety and many improvements to the API. Explicit state transitions is the major improvement that gives applications direct control of how state transitions must be handled by every draw command. There are two modes: automatic, where the engine keeps track of resource states and performs all required transitions, and manual, where the application takes control of state management. The second mode is most important in multi-threaded rendering scenarios. Check out the new release on GitHub.
    46. It's all relevant if you're programming. These principles aren't some way to brow beat people into line or for gate keeping (though there are people that do do things like that with them), the OOP principles really do help you to efficiently write code that is easier to maintain and plays well with others. No one starts off with this stuff already, it takes time and experience to get things going well. As a hobbyist, read up on it, take it in a little at a time. Every once in a while (like every year or two), review the principles again. Each time you do you will learn a little more because you'll be a little higher up the mountain.
    47. So, as a hobbyist, with minimal formal training in C++ or object oriented programming, how relevant is this stuff to me? Feels like just a lot of discussion waaaaay above my head rn :).
    48. lawnjelly

      Angular velocity and water physics

      Sounds a good solution, thanks! Also the magic number to be applied might need to vary with the size of the boat, I'll have to test it out.. and I could turn off the righting if the boat has capsized.
    49. Hello, I have a 'join'-function that joins an array's elements to a string. This is what I want: vector<int> a = {1,2,3} array<int, 3> b = {1,2,3} cout << join(a) << endl; // "1, 2, 3" cout << join(b) << endl; // "1, 2, 3" So I'm trying to declare the function this way: template <typename T, typename C> string join(const C<const T> &arr, const string &delimiter = ", "){ ... } But without any success. I understand, that I could declare it this way: template <typename T> string join(T &arr){ ... } or this way: template <typename Iter> string join(Iter &begin, Iter &end){ ... } But I just wonder, is it possible to implement it like: template <typename T, typename Collection> string join(const Collection<const T> &data){ ... } Thank you!
    50. JoeJ

      Angular velocity and water physics

      Yes, because the boat is more longer than wide, the clipped volume center can move forth and back more than sideways, so the torque can be larger accordingly. You could multiply the sideways dimension of your angular velocity in local ship space by 3 to fake this.
    51. Damn, good luck trying to take down OOP. There are plenty of bad examples of everything, but the tough thing to do is to take the principles as they are meant to be followed and address those directly. In this way you're attacking not just the best examples, you are addressing the ideal. Addressing only the bad examples or if we're being generous, what you find to be the common examples, is like playing your ideal team against the bench warmers and injured players of the other. Which is what it looks like you're doing here. If you follow SOLID, GRASP and the very common KISS principle, then none of the problems you listed as inherent to OOP (I think you are incorrect in doing so), are problems for OOP. I recommend following principles to about 90-95% because that's about the peak balance between development time and the benefits of the principle.
    52. I know very little about Ogre, but typically you'd use vertex colors for this, with vertex positions (and other attributes if necessary) duplicated as needed to facilitate differently colored edges. If Ogre is anything like other rendering engines, I'd assume you can create custom meshes with arbitrary data and vertex formats. You said you're feeding the renderer vertex and index buffers, so presumably there's a way to incorporate color attributes as well.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!