Beispiel #1
0
void tSimpleCopyPoints(aiPoints *iobj, aePoints *eobj)
{
    aiPointsData idata;
    aePointsData edata;
    int n = aiSchemaGetNumSamples(iobj);
    for (int i = 0; i < n; ++i) {
        auto ss = aiIndexToSampleSelector(i);
        aiSchemaUpdateSample(iobj, &ss);
        auto *sample = aiSchemaGetSample(iobj, &ss);
        aiPointsGetDataPointer(sample, &idata);

        edata.positions     = idata.positions;
        edata.velocities    = idata.velocities;
        edata.ids           = idata.ids;
        edata.count         = idata.count;

        aePointsWriteSample(eobj, &edata);
    }
}
tCLinkage tExport void tPointsExpanderConvert(tContext *tctx_, const PointsExpanderConfig *conf)
{
    tContext& tctx = *tctx_;
    tLogSetCallback(conf->logCB);

    tctx.setPointsProcessor([&](aiPoints *iobj, aePoints *eobj) {
        double time_proc_begin = tGetTime();
        const char* target_name = aiGetNameS(aiGetParent(aiSchemaGetObject(iobj)));
        tLog("processing \"%s\"\n", target_name);

        tPointsBuffer buf;
        std::vector<uint64_t> ids, ids_tmp1, ids_tmp2;
        std::vector<char> point_info;

        aiPointsSummary summary;
        aiPointsGetSummary(iobj, &summary);


        int num_samples = aiSchemaGetNumSamples(iobj);

        // build list of all ids
        for (int i = 0; i < num_samples; ++i) {
            auto ss = aiIndexToSampleSelector(i);

            aiSchemaUpdateSample(iobj, &ss);
            auto *sample = aiSchemaGetSample(iobj, &ss);

            aiPointsData idata;
            aiPointsGetDataPointer(sample, &idata);

            ids_tmp1.assign(idata.ids, idata.ids + idata.count);
            ist::parallel_sort(ids_tmp1.begin(), ids_tmp1.end());

            ids_tmp2.resize(ids_tmp1.size() + ids.size());
            std::merge(ids_tmp1.begin(), ids_tmp1.end(), ids.begin(), ids.end(), ids_tmp2.begin());
            ids_tmp2.erase(std::unique(ids_tmp2.begin(), ids_tmp2.end()), ids_tmp2.end());
            ids.assign(ids_tmp2.begin(), ids_tmp2.end());
        }
        tLog("  listed all IDs. %d elements (%.2lfms)\n", (int)ids.size(), tGetTime() - time_proc_begin);

        // 
        size_t info_size = size_t(sizeof(tPointInfoHeader) + sizeof(tPointInfo) * std::ceil(conf->count_rate));
        uint64_t id_range = summary.maxID - summary.minID + 1;
        point_info.resize(info_size * (size_t)id_range);

        auto getPointInfoByID = [&](uint64_t id) -> tPointInfoHeader& {
            return (tPointInfoHeader&)point_info[info_size * size_t(id - summary.minID)];
        };

        tRandSetSeed(conf->random_seed);
        uint64_t id_size_scaled = uint64_t((double)ids.size() * conf->count_rate);
        for (size_t pi = 0; pi < id_size_scaled; ++pi) {
            size_t spi = size_t((double)pi / conf->count_rate);
            uint64_t id = ids[spi];
            tPointInfo &pf = getPointInfoByID(id).push();
            pf.id = (uint32_t)pi;
            pf.random_diffuse = conf->random_diffuse * tRand3();
        }


        mpKernelParams mpparams;
        mpparams.damping = conf->repulse_damping;
        mpparams.advection = conf->repulse_advection;
        mpparams.max_particles = int(summary.peakCount * std::ceil(conf->count_rate));
        mpparams.particle_size = conf->repulse_particle_size;
        mpparams.pressure_stiffness = conf->repulse_stiffness;
        auto mp = mpCreateContext();

        // process all frames
        for (int fi = 0; fi < num_samples; ++fi) {
            double time_frame_begin = tGetTime();
            auto ss = aiIndexToSampleSelector(fi);

            // get points data from alembic
            aiSchemaUpdateSample(iobj, &ss);
            auto *sample = aiSchemaGetSample(iobj, &ss);
            aiPointsData idata;
            aiPointsGetDataPointer(sample, &idata);

            // create inc/decreased points buffer
            size_t num_scaled = 0;
            for (int pi = 0; pi < idata.count; ++pi) {
                tPointInfoHeader& pinfo = getPointInfoByID(idata.ids[pi]);
                num_scaled += pinfo.num;
            }
            buf.allocate(num_scaled, idata.velocities != nullptr);

            for (int pi = 0, spi = 0; pi < idata.count; ++pi) {
                getPointInfoByID(idata.ids[pi]).each([&](const tPointInfo &pinfo) {
                    buf.positions[spi] = (float3&)idata.positions[pi] + pinfo.random_diffuse;
                    buf.ids[spi] = pinfo.id;
                    if (idata.velocities) {
                        buf.velocities[spi] = (float3&)idata.velocities[pi];
                    }
                    ++spi;
                });
            }


            // repulsion
            if (conf->repulse_iteration > 0) {
                mpparams.world_center = (mpV3&)idata.center;
                mpparams.world_extent = (mpV3&)idata.size;
                mpparams.world_div = mpV3i(
                    std::min<int>(int(mpparams.world_extent.x * 2.0f / conf->repulse_particle_size), 256),
                    std::min<int>(int(mpparams.world_extent.y * 2.0f / conf->repulse_particle_size), 256),
                    std::min<int>(int(mpparams.world_extent.z * 2.0f / conf->repulse_particle_size), 256) );

                // apply repulsion
                mpSetKernelParams(mp, &mpparams);
                mpClearParticles(mp);
                mpForceSetNumParticles(mp, (int)num_scaled);
                mpParticle *particles = mpGetParticles(mp);
                for (size_t pi = 0; pi < num_scaled; ++pi) {
                    particles[pi].position = (mpV3&)buf.positions[pi];
                    particles[pi].velocity = mpV3();
                    particles[pi].lifetime = std::numeric_limits<float>::max();
                    particles[pi].userdata = (int)pi;
                }
                for (int ri = 0; ri < conf->repulse_iteration; ++ri) {
                    mpUpdate(mp, conf->repulse_timestep);
                }
                ist::parallel_sort(particles, particles + num_scaled,
                    [](const mpParticle& a, const mpParticle& b) { return a.userdata < b.userdata; });

                for (size_t pi = 0; pi < num_scaled; ++pi) {
                    buf.positions[pi] = (float3&)particles[pi].position;
                }
                if (idata.velocities) {
                    for (size_t pi = 0; pi < num_scaled; ++pi) {
                        buf.velocities[pi] = (float3&)particles[pi].velocity;
                    }
                }
            }

            auto edata = buf.asExportData();
            aePointsWriteSample(eobj, &edata);

            tLog("  frame %d: %d -> %d points (%.2lfms)\n",
                fi, idata.count, (int)num_scaled, tGetTime() - time_frame_begin);
        }
        mpDestroyContext(mp);

        tLog("finished \"%s\" (%.2lfms)\n", target_name, tGetTime() - time_proc_begin);
    });

    tctx.doExport();
}