• Content count

  • Joined

  • Last visited

Community Reputation

2660 Excellent


About JoeJ

  • Rank
    Advanced Member

Personal Information

  • Interests
  1. * A system that translates to other languages * A virtual philosopher that has something to say But realistically - personally i have high interest. Looking up for something like a library once a year but never found any. (I guess the industry has only little interest: If we need a writer to write any text, we can hire a voice actor as well) Some ideas: Some language that discribes intonations, feelings and stuff, e.g. "<frightened 5> Help! The monster! <whispering 2> Hide under the desc!" Eventually a musician could also add this data in real time by playing along with a keyboard, controlling both pitch, mood etc. (I remember guitarist Steve Vai imitating spoken speech on guitar, and it really works well - he can express those things very accurate, although you can not understand the words themselves.) We need laaughter and screams, not just speech. Generating data usable for automatic lipsync and facial animation would be nice bonus. We might be happy with something that acts as a placeholder during production, and will be replaced by voice actors when everything is done. For now at least...
  2. Transforming Angular Velocity

    Axis and Angle: Axis has always unit length. "Rotation Vector" = axis * angle (so just 3 numbers instead 4) Unfortunately i don't know a common name for this - "Rotation Vector" is just my own term. Both of them can represent angular velocity because both support multiple revolutions, Rotation Vector is preferred because you can sum up multiple velocities before you perform any rotation. Yes (as long as they both represent a rotation / orientation. Exception is e.g. a scaled or sewed matrix. Quats can't handle this.) Don't know. You typically use only one integrator: You sum up all forces that affect an object, calculate velocity and integrate it for the time duration you want. In your case it's easier as you don;t deal with forces i guess. I see you integrated 3 times in your code but that's wrong - you want one single rotation that does the same as your 3 hardcoded rotations. So one single angular velocity calculated from 3 ordered rotations to integrate. I would do this for example for a problem like this: I have animation data with euler angles (which are 3 ordered rotations each as well), and i need to feed the physics engine of a game so a simulated rigid body matches the animation. I assume your problem is equivalent, and all my response is based on that assumption. (Why else would you want to calculate angular velocity? You don't tell me....) If you have some rotation matrices, multiply them in order, the result must be the same if you first convert each matrix to quat and multiply them in the same order. Check this out to be sure your math lib works as expected. You'd need to look at the numbers, probably there are zero rows or columns that cause this. Noooo! Angular velocity is not the difference between Euler Angles. This may work in special cases, e.g. two angles are zero or cancel each other out due to gimbal lock. But in general it's terribly wrong. The reason is Euler angles has a specified order. The angle numbers alone don't know that order, but you can't interpret them without defining that order. Taking the difference ignores all this. (I remember a game physics book that did that same mistake but not the title. If you have it, burn it.) Rule of the thumb: Avoid using euler angles unless you have a very good reason. Understanding 3D rotations requires practice and it's hard to communicate. To get better help you need to describe very precisely what your problem is in practice, and why you need to do conversations from a reference to something else.
  3. What you want is AFAIK impossible, you can't debug GPU code like CPU code. All you can do is implementing your own logging, e.g. use a buffer entirely for debugging reasons, store numbers to it from shader, print numbers from GPU. Some APIs (/ GPUs?) support true printf style outputs from shaders, but i never used that so don't know which. OpenCL with Intel SDK allows stepping into code like you expect, but only if it runs on CPU and you still need to specify workgroup and thread index, so still a bit annoying to use. After some time i get comfortable with using the debug buffer and rarely mess a real debugger (But if so - yep, it hurts )
  4. Looking at the convex decomposition image from that presentation it becomes clear to me that this is not really a option for detailed visual meshes. I think creating clusters of triangles with a bounding box might be better than sorting: Checking all boxes with brute force is fast, then checking all edges per cluster remembering split edges and eventually intersections. During the scissor walk results could be reused.
  5. Transforming Angular Velocity

    No, actually this normalization has no effect and should be removed. You and everybody else Thinking of it as an axis and angle rotation is good enough to work with them. It's more important to understand what you can do with various rotation representation, e.g.: Quat: Easy to interpolate, easy to convert to axis and angle Rotation Vector (axis times angle): You can sum multiple rotations, no angle limit Matrix: You can also represent scale and skew Euler angles: Good for numerical user interaction
  6. Transforming Angular Velocity

    You should post the code that produces the red sphere too, so i can figure out what you try to do. I assume you try to match physics to some animation - why so? Also, if you control a physical object by changing its velocity, typically you do not care about acceleration. You care about acceleration only if you control the object by torque. E.g. for a question like "i want angular velocity of (10,0,0) - what torque do i need to achieve this?" Here acceleration matters, but by setting velocity directly you bypass any current physical state and just change it. (I assume that's one cause of what you mean with oscillation) At this line: vec3 angularVelocityVector = GEMultiplyVectorAndScalar(GEAxisFromQuaternion(quaternion), GEAngleFromQuaternion(quaternion)); You calculate velocity from orientation after rotating 3 times. This makes no sense. You should calculate it from a rotation. Note the difference between both terms (comparing angular to linear stuff here): Orientation is like position or a point, describing state in space. Rotation is like a displacement or vector, describing a difference between two orientations, or how orientation changes if we rotate it. Differentiating between those two terms also when thinking about a problem helps a lot to deal with 3D rotations I do not differentiate between 'point' and 'vector' - that's always easy, but for 'orientation' vs. 'rotation' it really helps. So i assume you want to calculate a single rotation that has the same effect than applying your 3 hardcoded rotations in order. And then you want to convert this single rotation to angular velocity so a physical body matches the result. Is that correct? This is what my 'some code' snippet does. angleEulerRadians = GEAddVectors(angleEulerRadians, GEMultiplyVectorAndScalar(angularVelocityVector, globalTimeStep)); This makes no sense. If you need to convert to euler angles you need a function that does the conversation (worth its own topic), but i assume you don't need them so avoid them to do yourself a favour. You should do this instead: Give your final orientation to glLoatMatrix, or give a rotation to glMultMatrix or glRotate (the latter using axis and angle, not eulers) (assuming you work in global space and you are not inside a transform hierarchy or something)
  7. Ah yeah, i ignored you need to add new stuff no matter if you sort tris / edges or verts. So resorting (at least insert) unavoidable, which means you run over the entire sorted list to copy and resort it. Further, if you use 3 axis, you can't sort primitives but just indirection indices, so jumping around in memory a lot until you find first and last element in range, making a win over brute force again unlikely. I meant 3 independent sorted lists of indirect indices to triangles (or edges), and you pick the one best fitting the plane normal. The worse the fit, the larger becomes the volume containing potential intersecting edges. However, you spend a lot effort maintaining a data structure that you need only one times. Likely this has the same cost as brute force search while throwing other data out of cache. Convex decomposition to avoid all this seems much more attractive, which is necessary anyways if you want to do collision detection for the pieces. You could order the primitives themselves by morton code in memory, which improves caching in any case.
  8. Thought about it. It would work with minor modifications for something like a torus, but it would fail for a bumpy torus with sinks on the surface, so useless. Thought about presorting as well, but i end up preferring either a tree or sorting in 3 axis to lift the 1D restriction. And rebuilding / adapting that stuff for both split pieces? Only worth if you have really high resolution meshes. Checking all vertices against the plane has perfect caching so brute force will be hard to beat i guess. Note that if you restrict yourself to convex meshes the 'walk from random start towards the plane' approach will be best, similar runtime than hopping in a presorted list or walk a tree but no additional data structure required. Edit: Presorting does not require to rebuild or adapt anything after the slice, right? And using 3 axis and selecting the best fit should work as well? You would need to create a bounding box of the plane intersetion with the objects bounding box, and then check all edges within that i guess, (so still a lot in worst case).
  9. Yes, but you need to find multiple starting edges. But the mentioned optimization to find a start edge would fail: I could get stuck in a sink. (I'm not sure at what complexity this optimization would be a win anyways, due to the need to maintain more adjacency). There is however a algorithm to calculate a cut graph for a mesh that cuts it to a topological disc. (Using spanning tree and it's dual, i'd need to look it up...) Eventually you could precompute that cut graph, and then only check those edges to find intersecting edges. But i need to think about this for some time - not sure if it works yet... (Also unsure if you'd need to recalculate this graph for sliced pieces so you can slice tham again - that would be much worse than just checking all edges.)
  10. just to remove any ambiguity here, convex(?), you probably meant to say convex here, right? Ooops, i did it again. Convex is right, yes - fixed.
  11. All 3D. The routine processes a polygon with an array of 3 3D vectors, 'puv'. (I store 3D position and uv channels there) My vec has storage for 4 numbers, so in this case i use plane[3] to store the plane distance to the origin. (confusing, but seems i was too lazy to create a plane class.) The original code came along Michael Abrashs Graphics Programming Black Book.
  12. Not sure what that is, but i mean for each edge have indices to left / right triangle. Further The whole mesh needs consistent winding order (each triangle has clockwise vertices. The mesh needs to be closed... the typical requirements). Find a edge that intersects the plane, split it and go to the left trianlge, find the other edge of that triangle that intersects the plane and continue with the other triangle from that edge until you get back to the starting edge. During that add each split point to the volume / plane intersection polygon. No Set required. Processing any edge just once. Works only for convex meshes (otherwise need to find all starting edges, not just any single one). It's like cutting a mesh made of paper with a scissor, so just in order vs. poking individual cuts into random triangles like traditional frustum clipping would do. (I've just implemented tracing a crossfield on mesh surface, which is pretty similar and i used this simple algorithm without issues.) Yeah you are right - the need to find a single intersecting edge kinda destroys the advantage we do not walk to triangles not touching the plane while cutting. But you could speed this up when everything else works as well: Pick a random vertex and select the edge closest to the plane, continue until you find an intersecting edge. Again this works only for the convex case (and you may need more adjacency information like vertex knowing all its edges - pretty annoying to maintain
  13. Look at this: really a good game as well. Slicing definitively realtime, remember software rendered games which did this for every polygon intersecting a frustum plane. Maybe look for polygon clipping. Here is a routine that i use in a preprocessing tool, but you need to build and triangulate the large poly where the volume intersects the plane alongside: Edit: Thinking of it, you should use only convex polyhedra, so slicing always results in only convex polygons. Complex shapes can be made by multiple convex shapes (like we do for physics collision detection). And if you have poly adjacency information at edges, you can slice in order so the volume poly emits in correct order as well and no searching is necessary to connect unordered split edges. This way you also quickly reject polys that do not intersect the splitting plane. inline int32_t ClipTexmapPolygon (const TexmapPolygon *pin, const vec &plane, TexmapPolygon *pout, const int32_t space) { if (pout->numAvailableVertices < pin->numVertices + 1) pout->Resize (pin->numVertices + 1); int32_t i, curin, nextin; float curdot, nextdot, scale; TexmapPolygon::Vertex *pinvert, *poutvert, *nextvert; pinvert = pin->vertices; poutvert = pout->vertices; curdot = pinvert->puv[space].Dot (plane); curin = (curdot >= plane[3]); int32_t ret = -1; // assume inside for (i=0; i<pin->numVertices; i++) { nextvert = &pin->vertices[(i+1) % pin->numVertices]; // keep if inside if (curin) { *poutvert++ = *pinvert; } nextdot = nextvert->puv[space].Dot (plane); nextin = (nextdot >= plane[3]); if (curin!=nextin) // add clipped vertex if plane splits edge { assert (fabs(nextdot - curdot) > FP_EPSILON); ret = 1; // clipped or outside scale = (plane[3] - curdot) / (nextdot - curdot); for (int32_t c=0; c<3; c++) poutvert->puv[c] = pinvert->puv[c] + (nextvert->puv[c] - pinvert->puv[c]) * scale; // position and 2 uc channels poutvert++; } curdot = nextdot; curin = nextin; pinvert++; } pout->numVertices = int32_t(poutvert - pout->vertices); if (pout->numVertices < 3) return 0; // outside return ret; }
  14. Transforming Angular Velocity

    This seems wrong (you need to use angle and time as well), it should be: vec3 angularVelocityVector = GEAxisFromQuaternion(quaternion) * GEAngleFromQuaternion(quaternion) * targetDuration; which would be the replacement for my confusing quat to angular velocity code. By using timestep for duration as i did you do the rotation as fast as possible - of course you can do it slower as well. Not sure what you intend with this. Looks wrong too. You can not add angular velocity to euler angles. Euler angles are always a series of 3 rotations in order, while angular velocity encodes a single rotation about its unit direction, by axis and speed encoded in its length. I guess this code is a try to integrate angular velocity? Here something simple i have, hope it helps: void IntegrateAgularVelocity (const sQuat &curOrn, const sVec3 &angvel, float timeStep, sQuat &predictedOrn) { sVec3 axis; float fAngle = angvel.Length(); if ( fAngle < float(0.00001) ) { predictedOrn = curOrn; return; } else { axis = angvel * (sin (fAngle * timeStep * float(0.5)) / fAngle); } sQuat dorn (axis.x(), axis.y(), axis.z(), cos (fAngle * timeStep * float(0.5))); predictedOrn = dorn * curOrn; predictedOrn.Normalize(); }
  15. Transforming Angular Velocity

    Some code: quat curOrientation = object.worldSpaceOrientation; quat targetOrientation = curOrientation; targetOrientation *= quat::FromaxisAndAngle(vec(1,0,0), PI*0.5f); targetOrientation *= quat::FromaxisAndAngle(vec(0,1,0), PI*-0.3f); targetOrientation *= quat::FromaxisAndAngle(vec(0,0,1), PI*1.5f); // now calculate rotation from current to target quat diff; quat &qA = curOrientation; &quat qB = targetOrientation; { quat q; if (qA.Dot(qB) < 0.0f) // use dot product so we pick the shortest arc rotation, and invert either axis or angular part { q[0] = qA[0]; q[1] = qA[1]; q[2] = qA[2]; q[3] = -qA[3]; } else { q[0] = -qA[0]; q[1] = -qA[1]; q[2] = -qA[2]; q[3] = qA[3]; } diff = qB * q; } // now convert diff to angular velocitiy float targetDuration = timestep; vec3 angVel (0,0,0); { // this is axis to angle conversation as you expect, but with some confusing 'fix close to zero angle issues' approach. const float matchTolerance = 0.0001f; const float faultTolerance = 0.0005f; quat q = diff; vec3 *omegaDir = (vec3*)&q; float sql = omegaDir.Dot(omegaDir); if (sql > (matchTolerance * matchTolerance)) { float length = sqrt (sql); if (q[3] < -1) q[3] = -1; if (q[3] > 1) q[3] = 1; angVel = (*omegaDir / length) * (2.0 * acos(q[3])); if (length < faultTolerance) angVel *= (length - matchTolerance) / (faultTolerance - matchTolerance); angVel *= targetDuration; } } If we integrate angVel for targetDuration, we reach targetOrientation as desired, but we won't have zero velocity, so the body will keep spinning so overshooting the target. The easiest way to avoid this is to recalculate angVel every step, but then integrate only a fraction of it like angVel*0.3 This way the body will come to rest at desired orientation, but no longer we are able to tell how long it will take exactly. I think my math lib has unusual rotation order, so when i write diff = qB * q, you may need to write diff = q * qB eventually.