1. //
  2. //  Dice.m
  3. //  DiceRoller
  4. //
  5. //  Created by Jacques Questiaux on 2012/04/17.
  6. //  Copyright (c) 2012 j.questiaux@gmail.com. All rights reserved.
  7. //
  8.  
  9. #import "Dice.h"
  10. #import "d4.h"
  11. #import "d6.h"
  12. #import "d8.h"
  13. #import "d10.h"
  14. #import "d12.h"
  15. #import "d20.h"
  16. #import "d100.h"
  17.  
  18. #include "btBulletDynamicsCommon.h"
  19.  
  20. typedef struct {
  21.     float r;
  22.     float g;
  23.     float b;
  24.    
  25. } Color;
  26.  
  27. Color faceColors [] ={
  28.    
  29.     {1, 0, 0},
  30.     {0, 0, 1},
  31.     {0, 1, 0},
  32.     {1, 1, 0},
  33.     {1, 0, 1},
  34.     {0, 1, 1},
  35.     {1, 1, 1},
  36.     {0.1, 0.1, 0.1}
  37. };
  38.  
  39. Color numbers [] ={
  40.    
  41.     {1, 1, 1},
  42.     {1, 1, 1},
  43.     {0, 0, 0},
  44.     {0, 0, 0},
  45.     {0, 0, 0},
  46.     {0, 0, 0},
  47.     {0, 0, 0},
  48.     {1, 1, 1}
  49. };
  50.  
  51. @interface Dice () {
  52.    
  53.     GLuint _vertexArray;
  54.     GLuint _vertexBuffer;
  55.     GLuint _indexBuffer;
  56.     GLuint _colorBuffer;
  57.     GLuint _normalBuffer;
  58.     GLuint _textureBuffer;
  59.    
  60.     GLuint toon_vertexArray;
  61.     GLuint toon_vertexBuffer;
  62.     GLuint toon_indexBuffer;
  63.    
  64.     GLfloat *vertices;
  65.     GLushort *indices;
  66.     GLfloat *normals;
  67.     GLfloat *colors;
  68.     GLfloat *tex;
  69.    
  70.     int numVertices;
  71.     int numIndices;
  72.     int numNormals;
  73.     int numColors;
  74.     int numTex;
  75.    
  76.     btDynamicsWorld *dynamicsWorld;
  77.     btRigidBody *diceRigidBody;
  78.    
  79.     btConvexHullShape *fallShape;
  80.     btDefaultMotionState *fallMotionState;
  81. }
  82.  
  83. @end
  84.  
  85. @implementation Dice
  86.  
  87. @synthesize up = _up;
  88. @synthesize front = _front;
  89. @synthesize right = _right;
  90. @synthesize position =_position;
  91. @synthesize direction = _direction;
  92. @synthesize modelViewMatrix = _modelViewMatrix;
  93.  
  94. - (id) initWithSides:(NSUInteger)s Color: (int) c{
  95.    
  96.     if(self = [super init]){
  97.        
  98.         Sides = s;
  99.         colorSelected = c;
  100.        
  101.         return self;
  102.     }
  103.    
  104.     return nil;
  105. }
  106.  
  107. - (id)initWithCoder:(NSCoder *)coder {
  108.    
  109.     if (self = [super init]) {
  110.  
  111.         Sides = [coder decodeIntegerForKey:@"Sides"];
  112.         colorSelected = [coder decodeFloatForKey:@"Color"];
  113.        
  114.         return self;
  115.     }
  116.    
  117.     return nil;
  118.    
  119. }
  120.  
  121. - (void)encodeWithCoder:(NSCoder *)coder {
  122.    
  123.     [coder encodeInteger:Sides forKey:@"Sides"];
  124.     [coder encodeFloat:colorSelected forKey:@"Color"];
  125. }
  126.  
  127. - (void) Context: (EAGLContext *) c Effect: (Effects *) e DynamicsWorld: (btDynamicsWorld *) d View: (GLKView *) v {
  128.    
  129.     self.right = GLKVector3Make(1, 0, 0);
  130.     self.up = GLKVector3Make(0, 1, 0);
  131.     self.front = GLKVector3Make(0, 0, 1);
  132.    
  133.     context = c;
  134.     effect = e;
  135.     dynamicsWorld = d;
  136.     view = v;
  137.    
  138.     friction = 0.95f;
  139.    
  140.     selected = false;
  141.     matrix = new btScalar[15];
  142.    
  143.     [self setup];
  144. }
  145.  
  146. - (void) setup{
  147.    
  148.     fallShape = new btConvexHullShape();
  149.    
  150.     //too lazy to swap to a switch statement
  151.     if(Sides == 4){
  152.         vertices = d4vertices;
  153.         numVertices = sizeof(d4vertices)/sizeof(GLfloat);
  154.        
  155.         indices = d4indices;
  156.         numIndices = sizeof(d4indices)/sizeof(GLushort);
  157.        
  158.         normals = d4normals;
  159.         numNormals = sizeof(d4normals)/sizeof(GLfloat);
  160.        
  161.         tex = d4tex;
  162.         numTex = sizeof(d4tex)/sizeof(GLfloat);
  163.        
  164.         for(int i = 0; i < numVertices; i+=3){
  165.            
  166.             btVector3 vert = btVector3(d4PhysicsVertices[i], d4PhysicsVertices[i+1], d4PhysicsVertices[i+2]);
  167.             fallShape->addPoint(vert);
  168.         }
  169.        
  170.     }
  171.     else if(Sides == 6){
  172.         vertices = d6vertices;
  173.         numVertices = sizeof(d6vertices)/sizeof(GLfloat);
  174.        
  175.         indices = d6indices;
  176.         numIndices = sizeof(d6indices)/sizeof(GLushort);
  177.        
  178.         normals = d6normals;
  179.         numNormals = sizeof(d6normals)/sizeof(GLfloat);
  180.        
  181.         tex = d6tex;
  182.         numTex = sizeof(d6tex)/sizeof(GLfloat);
  183.        
  184.         for(int i = 0; i < numVertices; i+=3){
  185.            
  186.             btVector3 vert = btVector3(d6PhysicsVertices[i], d6PhysicsVertices[i+1], d6PhysicsVertices[i+2]);
  187.             fallShape->addPoint(vert);
  188.         }
  189.        
  190.     }
  191.     else if(Sides == 8){
  192.         vertices = d8vertices;
  193.         numVertices = sizeof(d8vertices)/sizeof(GLfloat);
  194.        
  195.         indices = d8indices;
  196.         numIndices = sizeof(d8indices)/sizeof(GLushort);
  197.        
  198.         normals = d8normals;
  199.         numNormals = sizeof(d8normals)/sizeof(GLfloat);
  200.        
  201.         tex = d8tex;
  202.         numTex = sizeof(d8tex)/sizeof(GLfloat);
  203.        
  204.         for(int i = 0; i < numVertices; i+=3){
  205.            
  206.             btVector3 vert = btVector3(d8PhysicsVertices[i], d8PhysicsVertices[i+1], d8PhysicsVertices[i+2]);
  207.             fallShape->addPoint(vert);
  208.         }
  209.        
  210.     }
  211.     else if(Sides == 10){
  212.         vertices = d10vertices;
  213.         numVertices = sizeof(d10vertices)/sizeof(GLfloat);
  214.        
  215.         indices = d10indices;
  216.         numIndices = sizeof(d10indices)/sizeof(GLushort);
  217.        
  218.         normals = d10normals;
  219.         numNormals = sizeof(d10normals)/sizeof(GLfloat);
  220.        
  221.         tex = d10tex;
  222.         numTex = sizeof(d10tex)/sizeof(GLfloat);
  223.        
  224.         for(int i = 0; i < numVertices; i+=3){
  225.            
  226.             btVector3 vert = btVector3(d10PhysicsVertices[i], d10PhysicsVertices[i+1], d10PhysicsVertices[i+2]);
  227.             fallShape->addPoint(vert);
  228.         }
  229.        
  230.     }
  231.     else if(Sides == 100){
  232.         vertices = d100vertices;
  233.         numVertices = sizeof(d100vertices)/sizeof(GLfloat);
  234.        
  235.         indices = d100indices;
  236.         numIndices = sizeof(d100indices)/sizeof(GLushort);
  237.        
  238.         normals = d100normals;
  239.         numNormals = sizeof(d100normals)/sizeof(GLfloat);
  240.        
  241.         tex = d100tex;
  242.         numTex = sizeof(d100tex)/sizeof(GLfloat);
  243.        
  244.         for(int i = 0; i < numVertices; i+=3){
  245.            
  246.             btVector3 vert = btVector3(d100PhysicsVertices[i], d100PhysicsVertices[i+1], d100PhysicsVertices[i+2]);
  247.             fallShape->addPoint(vert);
  248.         }
  249.        
  250.     }
  251.     else if(Sides == 12){
  252.         vertices = d12vertices;
  253.         numVertices = sizeof(d12vertices)/sizeof(GLfloat);
  254.        
  255.         indices = d12indices;
  256.         numIndices = sizeof(d12indices)/sizeof(GLushort);
  257.        
  258.         normals = d12normals;
  259.         numNormals = sizeof(d12normals)/sizeof(GLfloat);
  260.        
  261.         tex = d12tex;
  262.         numTex = sizeof(d12tex)/sizeof(GLfloat);   
  263.        
  264.         for(int i = 0; i < numVertices; i+=3){
  265.            
  266.             btVector3 vert = btVector3(d12PhysicsVertices[i], d12PhysicsVertices[i+1], d12PhysicsVertices[i+2]);
  267.             fallShape->addPoint(vert);
  268.         }
  269.  
  270.     }
  271.     else {
  272.         vertices = d20vertices;
  273.         numVertices = sizeof(d20vertices)/sizeof(GLfloat);
  274.        
  275.         indices = d20indices;
  276.         numIndices = sizeof(d20indices)/sizeof(GLushort);
  277.        
  278.         normals = d20normals;
  279.         numNormals = sizeof(d20normals)/sizeof(GLfloat);
  280.        
  281.         tex = d20tex;
  282.         numTex = sizeof(d20tex)/sizeof(GLfloat);
  283.        
  284.         for(int i = 0; i < numVertices; i+=3){
  285.            
  286.             btVector3 vert = btVector3(d20PhysicsVertices[i], d20PhysicsVertices[i+1], d20PhysicsVertices[i+2]);
  287.             fallShape->addPoint(vert);
  288.         }
  289.  
  290.     }
  291.    
  292.     glGenVertexArraysOES(1, &_vertexArray);
  293.     glBindVertexArrayOES(_vertexArray);
  294.    
  295.     glGenBuffers(1, &_indexBuffer);
  296.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
  297.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*sizeof(GLushort), indices, GL_STATIC_DRAW);
  298.    
  299.     glGenBuffers(1, &_vertexBuffer);
  300.     glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
  301.     glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
  302.    
  303.     glEnableVertexAttribArray(effect->vertCoord);        
  304.     glVertexAttribPointer(effect->vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);
  305.    
  306.     glEnableVertexAttribArray(effect->toon_vertCoord);        
  307.     glVertexAttribPointer(effect->toon_vertCoord, 3, GL_FLOAT, GL_FALSE, 0, 0);
  308.    
  309.     glGenBuffers(1, &_normalBuffer);
  310.     glBindBuffer(GL_ARRAY_BUFFER, _normalBuffer);
  311.     glBufferData(GL_ARRAY_BUFFER, numNormals*sizeof(GLfloat), normals, GL_STATIC_DRAW);
  312.    
  313.     glEnableVertexAttribArray(effect->normal);
  314.     glVertexAttribPointer(effect->normal, 3, GL_FLOAT, GL_FALSE, 0, 0);
  315.  
  316.     glGenBuffers(1, &_textureBuffer);
  317.     glBindBuffer(GL_ARRAY_BUFFER, _textureBuffer);
  318.     glBufferData(GL_ARRAY_BUFFER, numTex*sizeof(GLfloat), tex, GL_STATIC_DRAW);
  319.    
  320.     glEnableVertexAttribArray(effect->texCoord);
  321.     glVertexAttribPointer(effect->texCoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
  322.  
  323.     glBindVertexArrayOES(0);
  324.    
  325.     /*----- PHYSICS SETUP -----*/
  326.    
  327.     fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), btVector3(self.position.x,self.position.y,self.position.z))); //original position
  328.     btScalar mass = 0.1;
  329.     btVector3 fallInertia(0,0,0);
  330.     fallShape->calculateLocalInertia(mass, fallInertia);
  331.     btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
  332.     fallRigidBodyCI.m_restitution = 0.3;
  333.     diceRigidBody = new btRigidBody(fallRigidBodyCI);
  334.     diceRigidBody->setDamping(0.9,0.3);
  335.     //diceRigidBody->setLinearFactor(btVector3(1,1,1));
  336.     diceRigidBody->setAngularFactor(btVector3(1,1,1));
  337.    
  338.     dynamicsWorld->addRigidBody(diceRigidBody);
  339. }
  340.  
  341. - (void) tearDown {
  342.    
  343.     dynamicsWorld->removeRigidBody(diceRigidBody);
  344.     delete diceRigidBody;
  345.     delete fallShape;
  346.     delete fallMotionState;
  347.    
  348.     glDeleteBuffers(1, &_vertexBuffer);
  349.     glDeleteBuffers(1, &_indexBuffer);
  350.     glDeleteBuffers(1, &_colorBuffer);
  351.     glDeleteBuffers(1, &_normalBuffer);
  352.     glDeleteBuffers(1, &_textureBuffer);
  353.    
  354.     delete matrix;
  355. }
  356.  
  357. - (void) update: (float) timeSinceLastUpdate{
  358.    
  359.     tslu = timeSinceLastUpdate;
  360.    
  361.     btTransform trans;
  362.     diceRigidBody->getMotionState()->getWorldTransform(trans);
  363.     diceRigidBody->activate();
  364.    
  365.     self.position = GLKVector3Make(trans.getOrigin().getX(), trans.getOrigin().getY(), trans.getOrigin().getZ());
  366.    
  367.     trans.getOpenGLMatrix(matrix);
  368.    
  369.     self.right =    GLKVector3Make(matrix[0], matrix[1], matrix[2]);
  370.     self.up =       GLKVector3Make(matrix[4], matrix[5], matrix[6]);
  371.     self.front =    GLKVector3Make(matrix[8], matrix[9], matrix[10]);
  372.    
  373.     mvm = GLKMatrix4Make(self.right.x,      self.right.y,       self.right.z,       0,
  374.                          self.up.x,         self.up.y,          self.up.z,          0,
  375.                          self.front.x,      self.front.y,       self.front.z,       0,
  376.                          self.position.x,   self.position.y,    self.position.z,    1);
  377. }
  378.  
  379. - (void) draw {
  380.     [EAGLContext setCurrentContext:context];
  381.  
  382.     glBindVertexArrayOES(_vertexArray);
  383.    
  384.     effect->modelViewMatrix = mvm;
  385.     effect->numberColour = GLKVector4Make(numbers[colorSelected].r, numbers[colorSelected].g, numbers[colorSelected].b, 1);
  386.     effect->faceColour = GLKVector4Make(faceColors[colorSelected].r, faceColors[colorSelected].g, faceColors[colorSelected].b, 1);
  387.  
  388.     if(selected){
  389.         [effect drawOutline];
  390.         glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
  391.     }
  392.  
  393.     [effect prepareToDraw];
  394.     glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
  395. }
  396.  
  397. - (void) applyForceInDirection: (GLKVector3) dir {
  398.    
  399.     btVector3 v = btVector3(dir.x/3, dir.y/3, dir.z/3);
  400.    
  401.     diceRigidBody->applyForce(v, btVector3(0, 0, 0));
  402.    
  403.     btVector3 t = v.cross(btVector3(0, 0, -1));
  404.     t.normalized();
  405.     t *= 0.45f;
  406.    
  407.     diceRigidBody->applyTorque(t);
  408.    
  409. }
  410.  
  411. GLKVector3 gluProject(GLKVector3 position,
  412.                       GLKMatrix4 projMatrix,
  413.                       GLKMatrix4 modelMatrix,
  414.                       CGRect viewport
  415.                       )
  416. {
  417.     GLKVector4 in;
  418.     GLKVector4 out;
  419.    
  420.     in = GLKVector4Make(position.x, position.y, position.z, 1.0);
  421.    
  422.     out = GLKMatrix4MultiplyVector4(modelMatrix, in);
  423.     in = GLKMatrix4MultiplyVector4(projMatrix, out);
  424.    
  425.     if (in.w == 0.0) NSLog(@"W = 0 in project function\n");
  426.     in.x /= in.w;
  427.     in.y /= in.w;
  428.     in.z /= in.w;
  429.     /* Map x, y and z to range 0-1 */
  430.     in.x = in.x * 0.5 + 0.5;
  431.     in.y = in.y * 0.5 + 0.5;
  432.     in.z = in.z * 0.5 + 0.5;
  433.    
  434.     /* Map x,y to viewport */
  435.     in.x = in.x * viewport.size.width + viewport.origin.x;
  436.     in.y = in.y * viewport.size.height + viewport.origin.y;
  437.    
  438.     return GLKVector3Make(in.x, in.y, in.z);
  439.    
  440. }
  441.  
  442. - (GLKVector2) getScreenCoordOfDice {
  443.        
  444.     GLKVector3 out = gluProject(self.position, effect->projectionMatrix, effect->cameraMatrix, view.frame);
  445.    
  446.     return GLKVector2Make(out.x,view.frame.size.height - out.y);
  447. }
  448.  
  449. @end