Git Product home page Git Product logo

bullet-xna's People

Contributors

xexuxjy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

bullet-xna's Issues

Missing GImpactMeshShape and GImpactCollisionAlgorithm

The description says that all collision shapes are implemented, however 
GImpactMeshShape and GImpactCollisionAlgorithm are not.   

Currently, the only concave triangle mesh that bullet supports in Dynamics is 
the GImpactMeshShape.  The bvhTriangleMesh works for stationary objects.

Might want to put this in the 'todo' section.

Original issue reported on code.google.com by [email protected] on 7 Apr 2011 at 5:29

Pachinko demo issue

Thank you for what you did on the Pachinko demo. It shows my problems and they 
are not eliminated. Make the radius of the sphere equal to 0.9. The ball does 
not pass between the pins even though the distance allows.

float ballRadius = 0.9f;

Original issue reported on code.google.com by [email protected] on 25 Nov 2012 at 9:57

DiscretDynamicsWorld.SetGravity's disabled gravity test is inverted

In DiscretDynamicsWorld.SetGravity:

  if (body.IsActive() && ((body.GetFlags() & RigidBodyFlags.BT_DISABLE_WORLD_GRAVITY) != 0))

should be

  if (body.IsActive() && ((body.GetFlags() & RigidBodyFlags.BT_DISABLE_WORLD_GRAVITY) == 0))

so that objects which have gravity enabled are actually updated, rather than 
the opposite.

(See also: 
http://bulletphysics.org/Bullet/BulletFull/btDiscreteDynamicsWorld_8cpp_source.h
tml#l00516)

Original issue reported on code.google.com by [email protected] on 20 Apr 2013 at 2:10

Demos - wrong camera aspect ratio

Aspect ratio of the camera is wrong due to the division of integer screen size 
values in the DemoApplication's ctor.

This
m_aspect = m_glutScreenWidth / m_glutScreenHeight; //(800/600 = 1)

should be changed to

m_aspect = m_glutScreenWidth / (float)m_glutScreenHeight; //(800/600 = 1.333)

Original issue reported on code.google.com by [email protected] on 5 Jan 2013 at 12:19

A different C# bullet interpretation

Hey there again.   

A while back, I attempted a CSharp bullet convert.   It failed...  but it might 
be useful to you.   You might want to look it over and see if it could benefit 
the project at all.   

Regards

Dan

Original issue reported on code.google.com by [email protected] on 10 Jun 2011 at 6:13

Attachments:

Fix for NullReferenceException when removing the last child in CompoundShape

When removing a child shape from a CompoundShape, RemoveChildShapeByIndex uses 
ObjectArray.RemoveAtQuick to replace the node by putting the last one in its 
place.

RemoveChildByShapeIndex will then update the newly placed node's dataAsInt 
value.

All this works fine, except for the case where we removed the last node, since 
in this case, no new node took its place and we end up trying to update a null 
object's dataAsInt value.

The (straightforward) patch to fix this is attached.

Original issue reported on code.google.com by [email protected] on 23 Aug 2013 at 1:57

Attachments:

Collision with the HeightfieldTerrainShape and CapsuleShapeZ objects never clears.

What steps will reproduce the problem?
1. My Coordinate space is X(forward), Y (side), Z(up) (units are meters)
2. The HeightField is set to use upaxis 2(Z) and a byte[] of 256x256 floats in 
(y * 256) + x form.   All floats are 21m.
3. Dropping a RigidBody with a CapsuleShapeZ as it's collision shape onto the 
heightfield results in a perpetual collision until the heightfield is recreated.

What version of the product are you using? On what operating system?
r6 using monoxna for an XNA library substitute.

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 7 Apr 2011 at 5:13

Multithreaded uses of bullet-xna in simultanious but separated worlds results in BulletXNA.LinearMath.PooledType corruption.

What steps will reproduce the problem?
1.  Start two threads that each create their own DiscreteDynamicsWorld
2.  Step the worlds Simultaniously on the separate threads repeatedly
3.  *unnecessary

What is the expected output? What do you see instead?

Expected: Worlds step happily.    

Result: BulletGlobals.PooledType<X> types get corrupted by one thread calling 
new T() and the other thread calling Free(T) making the T Get() call return a 
reference to null.

What version of the product are you using? On what operating system?
Latest dev (not stable version)


Please provide any additional information below.

An easy fix to this issue is to lock in PooledType<T> but the easiest fix isn't 
always the best option.   A lock in PooledType<T> would be very slow.    A 
better option is to more carefully select when PooledType<T> can and should be 
used and avoiding globals so the class data can be successfully encapsulated.

Original issue reported on code.google.com by [email protected] on 16 Aug 2013 at 7:32

Incorrect debug rendering of AABB for static box shapes by CollisionWorld

(Patch is attached)

If a static rigid body with a box shape is moved away from the origin, the AABB 
drawn by CollisionWorld is incorrect. It surrounds both the box in its 
translated position, and the box at the origin.

The problem seems to be in CollisionWorld.DebugDrawWorld, starting with the 
following line:
if(colObj.GetInternalType()==CollisionObjectTypes.CO_RIGID_BODY)

The actual Bullet library uses the following line instead:
if(getDispatchInfo().m_useContinuous && 
colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY && 
!colObj->isStaticOrKinematicObject())
(http://code.google.com/p/bullet/source/browse/trunk/src/BulletCollision/Collisi
onDispatch/btCollisionWorld.cpp)

This causes it to properly ignore GetInterpolationWorldTransform for the static 
rigid body, which seems to be returning the origin even when the box has been 
translated.

Original issue reported on code.google.com by [email protected] on 9 Aug 2012 at 4:37

Attachments:

[Info} Performance Profile Result

A friend of mine supplied an environment that they used to test and develop the 
parametric mesh generator.  It has about 1200 different mesh shapes for each of 
the different generation situations.  

The steps took about 1400ms with the scene in BulletXNA so I have not tested 
collisions on it yet, however, since BulletXNA was stressed, I figured I'd put 
it through a profiler and give you a report on the performance situation.   

Original issue reported on code.google.com by [email protected] on 19 Apr 2011 at 6:05

Attachments:

Larger Tri-Mesh triangles can be walked through.

Create a TriMesh like:  (pyramid) Object A
vertexList
Microsoft.Xna.Framework.Vector3[16]}
    [0]: {X:1.78321 Y:1.78321 Z:-1.783479}
    [1]: {X:1.78321 Y:-1.78321 Z:-1.783479}
    [2]: {X:-1.78321 Y:-1.78321 Z:-1.783479}
    [3]: {X:-1.78321 Y:1.78321 Z:-1.783479}
    [4]: {X:0 Y:0 Z:1.783479}
    [5]: {X:0 Y:0 Z:1.783479}
    [6]: {X:0 Y:0 Z:1.783479}
    [7]: {X:0 Y:0 Z:1.783479}
    [8]: {X:-1.78321 Y:-1.78321 Z:-1.783479}
    [9]: {X:0 Y:0 Z:1.783479}

indexList 
{int[256]}
    [0]: 0
    [1]: 1
    [2]: 2
    [3]: 3
    [4]: 0
    [5]: 2
    [6]: 4
    [7]: 5
    [8]: 6
    [9]: 4
    [10]: 6
    [11]: 7
    [12]: 4
    [13]: 2
    [14]: 1
    [15]: 4
    [16]: 1
    [17]: 5
    [18]: 5
    [19]: 1
    [20]: 0
    [21]: 5
    [22]: 0
    [23]: 6
    [24]: 6
    [25]: 0
    [26]: 3
    [27]: 6
    [28]: 3
    [29]: 7
    [30]: 7
    [31]: 3
    [32]: 8
    [33]: 7
    [34]: 8
    [35]: 9
    [36]: 9
    [37]: 8
    [38]: 2
    [39]: 9
    [40]: 2
    [41]: 4

and a box with halfextents 0.2  Object B

Rotate the tri-mesh 180 degrees on any horizontal axis

Box can move through the solid surfaces where there is no vertex near. Except 
for the rectangle base which is facing towards 'up'.


What version of the product are you using? On what operating system?
r9

Please provide any additional information below.
It looks like the box(Object B) is only colliding with the verticies and edges 
of Object A but missing collisions on surfaces facing 5 out of 6 directions 
where Object B isn't coming into direct contact with a vertex.

(object A)Tri-mesh, w/0 mass, with less space between the vertices work better 
because the RigidBody with mass(object B) collides with the vertices and edges 
even though it fails to collide with the surfaces.

Original issue reported on code.google.com by [email protected] on 15 Apr 2011 at 2:02

Remove using System.Linq;

This is fairly low in importance, however, there doesn't seem to be anything 
using System.Linq in BulletXNA.  By default, it's added to the usings when the 
class is created in visual studio even when it's not necessary.  Suggest 
removing them where appropriate.

Original issue reported on code.google.com by [email protected] on 2 Jun 2011 at 5:16

Assert on collision

What steps will reproduce the problem?
1.Assert on PooledType.Free

---- Assert Long Message ----

   at BulletXNA.LinearMath.PooledType`1.Free(T obj) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\LinearMath\PooledType.cs:line 24
   at BulletXNA.BulletCollision.SphereTriangleCollisionAlgorithm.Cleanup() in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\SphereTriangleCollisionAlgorithm.cs:line 70
   at BulletXNA.BulletCollision.ConvexTriangleCallback.ProcessTriangle(IndexedVector3[] triangle, Int32 partId, Int32 triangleIndex) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\ConvexConcaveCollisionAlgorithm.cs:line 449
   at BulletXNA.BulletCollision.BvhTriangleMeshShape.MyNodeOverlapCallback.ProcessNode(Int32 nodeSubPart, Int32 nodeTriangleIndex) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionShapes\BvhTriangleMeshShape.cs:line 328
   at BulletXNA.BulletCollision.QuantizedBvh.WalkStacklessQuantizedTree(INodeOverlapCallback nodeCallback, UShortVector3& quantizedQueryAabbMin, UShortVector3& quantizedQueryAabbMax, Int32 startNodeIndex, Int32 endNodeIndex) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\BroadphaseCollision\QuantizedBvh.cs:line 717
   at BulletXNA.BulletCollision.QuantizedBvh.ReportAabbOverlappingNodex(INodeOverlapCallback nodeCallback, IndexedVector3& aabbMin, IndexedVector3& aabbMax) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\BroadphaseCollision\QuantizedBvh.cs:line 1014
   at BulletXNA.BulletCollision.BvhTriangleMeshShape.ProcessAllTriangles(ITriangleCallback callback, IndexedVector3& aabbMin, IndexedVector3& aabbMax) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionShapes\BvhTriangleMeshShape.cs:line 143
   at BulletXNA.BulletCollision.ConvexConcaveCollisionAlgorithm.ProcessCollision(CollisionObject bodyA, CollisionObject bodyB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\ConvexConcaveCollisionAlgorithm.cs:line 194
   at BulletXNA.BulletCollision.DefaultNearCallback.NearCallback(BroadphasePair collisionPair, CollisionDispatcher dispatcher, DispatcherInfo dispatchInfo) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\CollisionDispatcher.cs:line 361
   at BulletXNA.BulletCollision.CollisionPairCallback.ProcessOverlap(BroadphasePair pair) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\CollisionDispatcher.cs:line 323
   at BulletXNA.BulletCollision.HashedOverlappingPairCache.ProcessAllOverlappingPairs(IOverlapCallback callback, IDispatcher dispatcher) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\BroadphaseCollision\OverlappingPairCache.cs:line 265
   at BulletXNA.BulletCollision.CollisionDispatcher.DispatchAllCollisionPairs(IOverlappingPairCache pairCache, DispatcherInfo dispatchInfo, IDispatcher dispatcher) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\CollisionDispatcher.cs:line 190
   at BulletXNA.BulletCollision.CollisionWorld.PerformDiscreteCollisionDetection() in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletCollision\CollisionDispatch\CollisionWorld.cs:line 466
   at BulletXNA.BulletDynamics.DiscreteDynamicsWorld.InternalSingleStepSimulation(Single timeStep) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletDynamics\Dynamics\DiscreteDynamicsWorld.cs:line 811
   at BulletXNA.BulletDynamics.DiscreteDynamicsWorld.StepSimulation(Single timeStep, Int32 maxSubSteps, Single fixedTimeStep) in C:\Projects\gameprom\Slayer\SlayerXNA\ThirdParty\MonoGameEngine.Core\Physics\Engine\BulletDynamics\Dynamics\DiscreteDynamicsWorld.cs:line 147

Original issue reported on code.google.com by [email protected] on 19 Jul 2012 at 12:07

Examples

Hello,

Are there examples available how to use "bullet-xna" engine?

Thanks

Original issue reported on code.google.com by [email protected] on 11 Oct 2012 at 5:53

Some triangles on BvhTriMesh are inverted

Pretty consistently some triangles in BvhTriangleMeshShapes using IndexedMesh 
and TriangleIndexVertexArray are inverted and the normals are facing the wrong 
way.

  So..   we have an oval ellipsoid..   supposed to be like

     /\
     ||
  __________
/           \
|-\       /-|
|  ------   |
\___________/
     ||
     \/

but in bullet-xna, it ends up like:

      ||
      \/
  _||||||||_
/           \
|-\       /-|
|  -||||-   |
\__|||||||_/
      /\
      ||

and often results in Bodies getting stuck inside bvhTriangleShape collision 
objects.

Not all of the triangles are inverted, but about half of them are.  The 
triangles that are inverted are opposite each other on the shape.

           |
 (inverted)|
           |
     --------------
           |
           |  (inverted)
           |

I tested the exact code against the native bullet library and it gave me a 
proper collision shape..   so there seems to be a bug in the triangle 
orientation or normal direction.  

-------------------------------------
C# Code

internal static object CreateMeshShape2(object pWorld, int pIndicesCount, int[] 
indices, int pVerticesCount, float[] verticesAsFloats)
{
    ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
    ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
    var world = pWorld as DiscreteDynamicsWorld;
    IndexedMesh mesh = new IndexedMesh();
    mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
    mesh.m_numTriangles = pIndicesCount/3;
    mesh.m_numVertices = pVerticesCount;
    mesh.m_triangleIndexBase = indicesarr;
    mesh.m_vertexBase = vertices;
    mesh.m_vertexStride = 3;
    mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
    mesh.m_triangleIndexStride = 3;

    TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
    tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
    BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
    meshShape.SetMargin(world.WorldSettings.Params.collisionMargin);
    return meshShape;
}

C++ code (native lib)
// =====================================================================
// Mesh, hull, shape and body creation helper routines
EXTERN_C DLL_EXPORT btCollisionShape* CreateMeshShape2(Sim* sim, 
                        int indicesCount, int* indices, int verticesCount, float* vertices )
{
    btCollisionShape* shape = sim->CreateMeshShape2(indicesCount, indices, verticesCount, vertices);
    bsDebug_RememberCollisionShape(shape);
    return shape;
}

// If using Bullet' convex hull code, refer to following link for parameter 
setting
// http://kmamou.blogspot.com/2011/11/hacd-parameters.html
// Another useful reference for ConvexDecomp
// http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=7159

btCollisionShape* Sim::CreateMeshShape2(int indicesCount, int* indices, int 
verticesCount, float* vertices )
{
    //We must copy the indices and vertices since the passed memory is released when this call returns.
    btIndexedMesh indexedMesh;
    int* copiedIndices = new int[indicesCount];
    bsMemcpy(copiedIndices, indices, indicesCount * sizeof(int));
    int numVertices = verticesCount * 3;
    float* copiedVertices = new float[numVertices];
    bsMemcpy(copiedVertices, vertices, numVertices * sizeof(float));
    indexedMesh.m_indexType = PHY_INTEGER;
    indexedMesh.m_triangleIndexBase = (const unsigned char*)copiedIndices;
    indexedMesh.m_triangleIndexStride = sizeof(int) * 3;
    indexedMesh.m_numTriangles = indicesCount / 3;
    indexedMesh.m_vertexType = PHY_FLOAT;
    indexedMesh.m_numVertices = verticesCount;
    indexedMesh.m_vertexBase = (const unsigned char*)copiedVertices;
    indexedMesh.m_vertexStride = sizeof(float) * 3;
    btTriangleIndexVertexArray* vertexArray = new btTriangleIndexVertexArray();
    vertexArray->addIndexedMesh(indexedMesh, PHY_INTEGER);
    btBvhTriangleMeshShape* meshShape = new btBvhTriangleMeshShape(vertexArray, true, true);
    meshShape->setMargin(m_worldData.params->collisionMargin);
    return meshShape;
}

Original issue reported on code.google.com by [email protected] on 14 Dec 2012 at 10:03

BvhBroadphase add/remove bug

BvhBroadphase

In killercore - if you add all the entities to the broadphase, then remove 
them, then re-add them then the player falls through the level , even though 
the boxes for the levels seem to be correct in debugdraw.

Original issue reported on code.google.com by [email protected] on 11 Dec 2012 at 9:56

Matrix <-> IndexedMatrix conversion

-What steps will reproduce the problem?

var m = Matrix.CreateRotationY(MathHelper.PiOver2);
IndexedMatrix a = new IndexedMatrix(m);
Console.WriteLine(m);
Console.WriteLine(a.ToMatrix());

// result :
// { {M11:-4,371139E-08 M12:0 M13:-1 M14:0} {M21:0 M22:1 M23:0 M24:0} {M31:1 
M32:0 M33:-4,371139E-08 M34:0} {M41:0 M42:0 M43:0 M44:1} }
// { {M11:-4,371139E-08 M12:0 M13:1 M14:0} {M21:0 M22:1 M23:0 M24:0} {M31:-1 
M32:0 M33:-4,371139E-08 M34:0} {M41:0 M42:0 M43:0 M44:1} }

-What is the expected output? What do you see instead?
Both printed matrix should be the same, but here the basis is transposed 
(translation works fine)


-What version of the product are you using? On what operating system?
Tested on stable and last svn (187)


-Please provide any additional information below.
In the IndexedMatrix constructor, the Right, Up, and Backward properties of the 
Matrix are used as the Rows of the IndexedBasisMatrix, whereas the columns of 
the basis are used to set those three properties in the toMatrix() method.

One of the two is obviously wrong. Now when transforming coordinates vectors 
are multiplied as the right-operand in bullet and as the left one in XNA, the 
basis matrix actually need to be transposed, so I guess it's the 
Matrix->IndexedMatrix that should be corrected (so transforming a vector with a 
matrix and and it's indexed counterpart will give the same result)



Original issue reported on code.google.com by [email protected] on 25 Apr 2013 at 3:18

ClosestPointInput.m_maximumDistanceSquared not initialized in some places

Patch is attached.

In the original bullet library, the constructor of 
btDiscreteCollisionDetectorInterface::ClosestPointInput initializes 
m_maximumDistanceSquared to BT_LARGE_FLOAT, which is defined as 1e18f. (See 
BulletCollision\NarrowPhaseCollision\btDiscreteCollisionDetectorInterface.h)

bullet-xna does not initialize it in the constructor, but instead initializes 
it in a number of places where ClosestPointInput is used (to float.MaxValue).

ContinuousConvexCollision.ComputeClosestPoints() is not one of these places. 
This causes CollisionWorld.ConvexSweepTest() to not detect collisions in some 
cases where collisions should be detected. The attached patch adds the missing 
initialization.

(GjkConvexCast.CalcTimeOfImpact() might have the same problem, but I'm not sure)

Original issue reported on code.google.com by [email protected] on 28 Feb 2013 at 1:17

Attachments:

Hard tunneling

1.
I create DiscreteDynamicsWorld.If execute StepSimulation with parametrs:

StepSimulation((float)gameTime.ElapsedGameTime.TotalSeconds, 10, 1.0f / 60.f)

I get the tunneling effect. I have a ball on stage and a few 
BvhTriangleMeshShape. The ball passes through a static geometry.

If I change the update settings:
StepSimulation((float)gameTime.ElapsedGameTime.TotalSeconds, 10, 1.0f / 200.f)

There is no tunneling, the physics works fine. But the phone I can not get more 
than 2 fps.

How to eliminate the effect of tunneling.

2.
I have a couple of cylinders standing in several rows in a checkerboard 
pattern. Distance between the cylinders is enough to pass the ball between them.

But in place in order to pass the ball between the cylinders stuck in them or 
just does not pass between them. Sometimes the ball drops sharply to the left 
or right. Sometimes he stops and begins to tremble.

Tell me what the key problems.

Original issue reported on code.google.com by [email protected] on 13 Aug 2012 at 3:14

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.