আমি কীভাবে একটি খেলায় ডপলার প্রভাব অনুকরণ করতে পারি?


14

আমি একটি গেম (একটি গাড়ী রেসিং গেম) এ ডপলার প্রভাব অনুকরণ করার চেষ্টা করছি। আমি একটি নির্দিষ্ট শব্দ গ্রন্থাগার ব্যবহার করছি না যা প্রভাবটি অনুকরণ করে, আমার কেবলমাত্র একটি কলব্যাক ফাংশন আছে যেখানে আমি ডেটা মিশ্রিত করি।

আমি ইতিমধ্যে মিক্সার ফাংশনটিতে কোনও নমুনার ফ্রিকোয়েন্সি কীভাবে পরিবর্তন করব তা খুঁজে পেয়েছি।

আমি যা জানি না তা নির্ভর করে প্লেয়ার এবং ইমিটারের অবস্থান এবং গতিবেগ নির্ভর করে কতটা ফ্রিকোয়েন্সি পরিবর্তন করা উচিত।

গেমটিতে আমার যা আছে তা এখানে:

//player 
vec3 p.pos; 
vec3 p.vel;

//emitter 
vec3 e.pos;
vec3 e.vel;

1) উইকিপিডিয়া অনুসারে নির্গত ফ্রিকোয়েন্সি এবং পর্যবেক্ষণের ফ্রিকোয়েন্সিগুলির মধ্যে সম্পর্কটি নিম্নলিখিত দ্বারা প্রদত্ত:

float f = (c + vr) / (c + vs) * fo

যেখানে সি একটি ধ্রুবক হয়, মাঝারি গতিবেগ (সাধারণত একটি বড় সংখ্যা) বনাম এবং ভিআর হ'ল উত্স এবং রিসিভারের গতি মাধ্যমের তুলনায়।

তাই আমি অনুমান করি :

float vr = p.vel.length; //player speed 
float vs = e.vel.length; //emitter speed

কিন্তু আমি মনে করি তার ভুল, এটা অভ্যস্ত যেমন জন্য ফ্রিকোয়েন্সি কোন পরিবর্তন, উত্পাদন: যদি vr = 0(প্লেয়ার Dont পদক্ষেপ) এবং বিকিরণকারী ধ্রুবক গতি, তারপর আছে vrএবং vsঅভ্যস্ত পরিবর্তন করুন (যখন তারা উচিত)।

সম্ভবত আমি ইমিটারের বেগ তুলনামূলকভাবে প্লেয়ারের বেগ গণনা করব?

এটার মত :

relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);

তাহলে কীভাবে vrএবং vsখাওয়ানো উচিত?


২) উইকিপিডিয়া কোনও পর্যবেক্ষকের দ্বারা যানবাহনটির গাড়ির অনুকরণের জন্য আরও একটি সূত্র দেয়:

vr = vs * cos(theta);

//theta is angle between observer and emitter
//theta = atan2(e.pos.y-p.pos.y, e.pos.x-p.pos.x); ?

তবে, এই সূত্রটি ধরে নিই যে রিসিভারটি সরবে না, যা এখানে ঘটনা নয়। প্লেয়ার এবং ইমিটার যদি একই গতিতে (বা ছোট পার্থক্য) চলে যায় তবে কোনও ডপলার প্রভাব থাকতে হবে না। এই ফাংশনটি একটি ক্ষেত্রেও সুনির্দিষ্ট, আমি মনে করি চূড়ান্ত সূত্রটি একই রকমের হওয়া উচিত পরিস্থিতিটির কোনও কারণ নেই।


সম্পাদনা: আমি স্কিমফ্লাক্স পোস্টটি ব্যবহার করে সঠিক সূত্রটি সন্ধান করার চেষ্টা করছি:

vr,r = vr.vel * cos(shortest_angle_between ( vr.vel , vs.pos - vr.pos)); 
vs,r = vs.vel * cos(shortest_angle_between ( vs.vel , vr.pos - vs.pos)); 

//is there a easier/faster way to find them out ? 
//note: vr.vel and vs.vel are vectors, the green and red arrows on SkimFlux picture. 

সম্পাদনা 2:

আগ্রহীদের জন্য, এখানে চূড়ান্ত সূত্র:

vec2 dist = vs.pos - vr.pos;

vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)

দ্রষ্টব্য: এটি ভেক্টর অভিক্ষেপ ব্যবহার করে, এখানে বর্ণিত :

অভিক্ষেপ সূত্র

তারপরে vr,sএবং vs,rপ্রথম উইকিপিডিয়া সূত্রে ইনজেকশন দেওয়া উচিত:

এখানে চিত্র বর্ণনা লিখুন

আমি এটি পরীক্ষা করেছি এবং এটি সফলভাবে কাজ করে, দুর্দান্ত ফলাফল সরবরাহ করে।


3
আপনি যে সূত্রটি ধরে নিয়েছেন যে রিসিভারটি উত্সের আসল চলাচলটিকে রিসিভারের সাথে তার গতিবিধির সাথে প্রতিস্থাপন করে চলমান নয় তা ধরে নিয়ে যেতে পারেন।
yoozer8

উত্তর:


9

1) ধরে নিন যে উভয় বস্তু একই লাইনে চলেছে - (এটি আপনার উইকিপিডিয়া পৃষ্ঠায় লিখিত হয়েছে) আপনার উপসংহারটি সঠিক, এই পরিস্থিতিতে ধ্রুবক বেগ সহ, ফ্রিকোয়েন্সি শিফট স্থির থাকে। ফ্রিকোয়েন্সি শিফট পরিবর্তনের জন্য, Vsএসআর অক্ষের সাথে স্থিতিশীল তবে কোলিনিয়ার নয় এমন পরিস্থিতির জন্য, আপেক্ষিক গতি পরিবর্তন করতে হবে, সুতরাং সূত্র 2) ।

সূত্র 2) তবে বিভ্রান্ত করছে: উত্স বেগের রেডিয়াল / আপেক্ষিক উপাদান Vrহিসাবে এটি পড়া উচিত Vs,r

দয়া করে নোট করুন যে ডপলার প্রভাব কেবল বেগের উপর নির্ভর করে, আপনার কেবল এসআর অক্ষটি সন্ধানের জন্য অবস্থানগুলির প্রয়োজন।

সম্পাদনা করুন : এটি আপনাকে বেগটি বের করতে সহায়তা করবে, আপনার সূত্র 1: সহ পরিমাণ Vs,rএবং Vr,rপরিমাণগুলি ব্যবহার করতে হবে

ডপলার শিফটের জন্য আপেক্ষিক বেগ


ঠিক আছে আপনার উত্তর (এবং ছবি) জন্য আপনাকে ধন্যবাদ, এটি অনেক সাহায্য করে। এখন সবকিছু পরিষ্কার, আমার সূত্র 1 এবং 2 একত্রিত করা উচিত। যেমন আপনি ব্যাখ্যা করেছেন, সূত্র 2 উইল কার্যকর যখন বস্তুগুলি একই লাইনে না থাকে। শেষ অংশটি হ'ল ভিআর, আর এবং বনাম, আর। ভিআর, আর = ভিআরওয়েল * কোস (সংক্ষিপ্ত_আঙ্গি_ত্যাগী (vr.vel, vs.pos - vr.pos)); বনাম, আর = বনাম.ভেল * কোস (সংক্ষিপ্ত_াঙ্গি_ভুক্ত (বনাম.ভেল, ভিআরপিপস - বনাম.পোস)); // তাদের খুঁজে বের করার কোন সহজ / দ্রুত উপায় আছে? // নোট ভিআরওয়েল এবং বনাম। ভেক্টর, স্কিমফ্লাক্স ছবিতে সবুজ এবং লাল তীর।
tigrou

আমি প্রথম পোস্ট সম্পাদনা করেছি এবং সঠিক ফর্ম্যাটিং সহ সূত্র যুক্ত করেছি। আপনি তাদের পরীক্ষা করতে পারেন? (প্রথমবারের মতো আমি গেমদেব স্ট্যাকেক্সচেঞ্জ ব্যবহার করি i আমি জানতাম না যে উত্তরে রেখাটি ফেরত যাবে, এবং এই মন্তব্যটি 5 মিনিটের পরে লক হয়ে গেছে ...)
টাইগার 14 ই

@ user1083855 হ্যাঁ, এগুলি ঠিক দেখাচ্ছে। এটিকে সহজ / দ্রুততর করার একটি উপায় হ'ল জিমের পরামর্শ অনুসরণ করা এবং সূত্র 2 ব্যবহার করা) উভয়ের মধ্যে আপেক্ষিক চলনের সাথে। আমি মনে করি না যে এটি সত্যই একইরকম কারণ সত্য ডপলার প্রভাব সাউন্ড মিডিয়াম (বায়ু) এর সাথে সম্পর্কিত উভয় সত্তার বেগের উপর নির্ভর করে, তবে একটি গেমের পরিস্থিতিতে এটি সম্ভবত যথেষ্ট কাছাকাছি থাকবে এবং আপনাকে একটি ব্যয়বহুল কোস অপারেশন সংরক্ষণ করবে।
স্কিমফ্লাক্স

: ভাল, আসলে আমি ভি এটি অনেক সহজ উপায় R পাওয়া যায় নি, দ বনাম en.wikipedia.org/wiki/Vector_projection
tigrou

0

এক্সএসিটি-র জন্য, এখানে ডপলার পিচ স্কেলার ভেরিয়েবল নির্দিষ্ট করা উচিত, অর্থাৎ আপেক্ষিক গতি, যেখানে 1.0 একই গতি, তবে <1.0 ধীর এবং> 1.0 দ্রুত

আপনাকে কোডের জন্য ধন্যবাদ, যা আমি এই সি # এর এই অংশে স্থানান্তর করেছি, যেখানে পর্দার অবস্থান এবং একটি কিউয়ের মধ্যে একটি শব্দ গণনা করা হয়। অবিকল কাজ করে

soundElements.ForEach(e =>
            {
                var cuePosition = new Vector3(e.PhysicPosition, 0);
                var distance = cuePosition - ScreenCenter;
                var distanceLength = distance.Length();
                e.Cue.SetVariable("Distance", distanceLength);
                var dopplerPitchScalar = 1.0f;
                if (e.AssociatedBody != null)
                {
                    ///gamedev/23583/how-do-i-simulate-a-doppler-effect-in-a-game
                    var screenVelocity = Vector3.Dot(ScreenVelocity, distance) / distanceLength;
                    var cueVelocity = Vector3.Dot(new Vector3(e.AssociatedBody.LinearVelocity, 0), distance) / distanceLength;
                    var relativeVelocity = screenVelocity - cueVelocity;
                    dopplerPitchScalar = (1f + relativeVelocity / SoundEffect.SpeedOfSound) / (1f - relativeVelocity / SoundEffect.SpeedOfSound);
                    //Console.WriteLine($"C: {ScreenCenter}, V: {ScreenVelocity}, D: {dopplerPitchScalar}");
                }
                e.Cue.SetVariable("DopplerPitchScalar", dopplerPitchScalar);
            });

BTW।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.