object::object() { /* data */ mTrans = matrixAlloc(); mOrigin = new float[3]; mOriginEx = new float[3]; mAngle = new float[3]; mScale = new float[3]; matrixIdent(mTrans); vectorNull(mOrigin); vectorNull(mAngle); vectorUnit(mScale); /* physics */ mPosVel = new float[3]; mAngVel = new float[3]; vectorNull(mPosVel); vectorNull(mAngVel); mPosAcc = new float[3]; mAngAcc = new float[3]; vectorNull(mPosAcc); vectorNull(mAngAcc); mMovSpdMax = BIG_NUMBER; mRotSpdMax = BIG_NUMBER; mStyle = 0; mCollide = true; mTicks = -1; mTarget = NULL; /* attributes */ mParent = NULL; mChanged = true; }
xy_t vectorProject(xy_t p1, xy_t p2) { xy_t normal = vectorUnit(p2); v_t scalar = vectorDotProduct(p1, normal); normal.x *= scalar; normal.y *= scalar; return normal; }
vector rayTrace(Line *ray, Primitive **primitives, Light **lights, float r_idx) { Intersection *bestIntersection = NULL; vector retval = vectorCreate(0.0, 0.0, 0.0); for (int p = 0; p < 10; p++) { if (!primitives[p]) break; Intersection *thisIntersection = primitiveIntersect(primitives[p], ray); if (!bestIntersection) { bestIntersection = thisIntersection; continue; } if (thisIntersection && thisIntersection->distance < bestIntersection->distance) { free(bestIntersection); bestIntersection = thisIntersection; } } if (bestIntersection) { Primitive *primitive = bestIntersection->primitive; Material *material = primitive->material; vector mcolor = vectorMultiply(material->color, 0.0); vector N = primitiveNormal(primitive, bestIntersection); vector V = vectorUnit(vectorSubtraction(ray->end, ray->start)); for (int l = 0; l < 2; l++) { Light *light = lights[l]; vector lvec = vectorSubtraction(light->location, bestIntersection->intersectionPoint); vector pcolor = material->color; vector lcolor = light->color; Intersection *linter = NULL; Line *lightRay = makeLine(bestIntersection->intersectionPoint, light->location); float shade = 0.0; for (int p = 0; p < 3; p++) { if (primitives[p] == primitive) continue; if ((linter = primitiveIntersect(primitives[p], lightRay))) shade += 1.0 - linter->primitive->material->transparency; } free(lightRay); if (shade < 1.0) { if (material->specular > 0.0) { float sintensity = 0.0; vector L = vectorUnit(lvec); vector R = vectorSubtraction(L, vectorMultiply(N, 2 * vectorDotProduct(L,N))); float dot = vectorDotProduct(V, R); if (dot > 0.0) { sintensity = pow(dot, 20) * material->specular * light->intensity * (1.0 - shade); } if (sintensity > 0.0) { mcolor = vectorAddition(mcolor, vectorMultiply(lcolor, sintensity)); } } if (material->diffuse > 0.0) { float dintensity = material->diffuse * vectorDotProduct(vectorUnit(lvec), primitive->normal(bestIntersection->primitive, bestIntersection)) * light->intensity * (1.0 - shade); if (dintensity > 0.0) { mcolor = vectorAddition(mcolor, vectorMultiply(vectorCProduct(pcolor, lcolor), dintensity)); } } } free(linter); } if (material->reflection > 0.0) { vector R = vectorUnit(vectorSubtraction(V, vectorMultiply(N, 2 * vectorDotProduct(V,N)))); Line *rline = makeLine(vectorAddition(bestIntersection->intersectionPoint, vectorMultiply(R, EPS)), vectorAddition(bestIntersection->intersectionPoint, vectorMultiply(R, 30))); vector rcolor = rayTrace(rline, primitives, lights, r_idx); mcolor = vectorAddition(vectorMultiply(mcolor, 1.0 - material->reflection), vectorMultiply(rcolor, material->reflection)); free(rline); } if (material->transparency > 0) { float refraction = material->refraction; float n = r_idx / refraction; vector Nr = vectorMultiply(N, bestIntersection->direction); float cosI = - vectorDotProduct(Nr, V); float cosT2 = 1.0 - n * n * (1.0 - cosI * cosI); if (cosT2 > 0.0) { vector T = vectorAddition(vectorMultiply(V, n), vectorMultiply(Nr, n * cosI - sqrt(cosT2))); Line *rline = makeLine(vectorAddition(bestIntersection->intersectionPoint, vectorMultiply(T, EPS)), vectorAddition(bestIntersection->intersectionPoint, vectorMultiply(T, 30))); vector rfcol = rayTrace(rline, primitives, lights, r_idx); mcolor = vectorAddition(vectorMultiply(mcolor, 1.0 - material->transparency), vectorMultiply(rfcol, material->transparency)); free(rline); } } retval = mcolor; free(bestIntersection); } return retval; }
v_t vectorProjectScalar(xy_t p1, xy_t p2) { return vectorDotProduct(p1, vectorUnit(p2)); }